From 48e848d94b71006f4eb9cccce1f5595060f85e03 Mon Sep 17 00:00:00 2001 From: Gennady Verdel Date: Wed, 24 Nov 2021 18:29:20 +0200 Subject: [PATCH 1/3] chore: bump deps --- appveyor.yml | 2 +- devops/deploy/deploy-all.bat | 2 +- .../contents/LogoFX.Client.Core.Core.nuspec | 4 +-- .../contents/LogoFX.Client.Core.nuspec | 4 +-- .../contents/LogoFX.Client.Modularity.nuspec | 4 +-- .../contents/LogoFX.Client.Theming.nuspec | 2 +- .../LogoFX.Core/contents/LogoFX.Core.nuspec | 2 +- .../contents/LogoFX.Practices.IoC.nuspec | 6 ++-- devops/publish/publish-all.bat | 2 +- devops/publish/publish-single.bat | 2 +- .../Invocation.feature | 2 +- .../Invocation.feature.cs | 2 +- .../InvocationSteps.cs | 7 +++-- ....Client.Core.Platform.NETCore.Specs.csproj | 8 ++--- .../specflow.json | 2 +- .../android/Properties/AssemblyInfo.cs | 4 +-- .../android/Resources/Resource.Designer.cs | 2 +- .../iOS/Properties/AssemblyInfo.cs | 4 +-- .../LogoFX.Client.Core.Platform.NET.csproj | 4 +-- ...LogoFX.Client.Core.Platform.NETCore.csproj | 2 +- .../netframework/Properties/AssemblyInfo.cs | 4 +-- .../uwp/Properties/AssemblyInfo.cs | 4 +-- .../DispatcherScenarioDataStoreBase.cs | 0 .../InvocationScenarioDataStoreBase.cs | 0 .../LogoFX.Client.Core.Specs.Common.csproj | 25 ++++++++++++++++ .../NumberChangeSteps.cs | 29 +++++++++++++++++++ .../TestClass.cs | 0 .../TestClassFactory.cs | 13 +++++++++ .../TestClassHelper.cs | 14 ++++----- .../ValueWrapper.cs | 0 .../Common/CommonSteps.cs | 27 +++++------------ .../Common/TestClassFactory.cs | 13 --------- .../LogoFX.Client.Core.Specs.csproj | 11 +++---- .../NotifyPropertyChangedSteps.cs | 3 +- src/LogoFX.Client.Core.Specs/specflow.json | 27 ++++++++++------- .../LogoFX.Client.Core.csproj | 2 +- .../LogoFX.Client.Modularity.csproj | 4 +-- .../LogoFX.Client.Theming.Platform.NET.csproj | 4 +-- ...oFX.Client.Theming.Platform.NETCore.csproj | 2 +- .../netframework/Properties/AssemblyInfo.cs | 4 +-- .../LogoFX.Client.Theming.csproj | 2 +- src/LogoFX.Core.sln | 23 +++++++++++++-- src/LogoFX.Core/LogoFX.Core.csproj | 2 +- .../LogoFX.Practices.IoC.Modularity.csproj | 4 +-- .../LogoFX.Practices.IoC.Specs.csproj | 10 +++---- .../LogoFX.Practices.IoC.csproj | 2 +- 46 files changed, 182 insertions(+), 114 deletions(-) rename src/{LogoFX.Client.Core.Specs/Common => LogoFX.Client.Core.Specs.Common}/DispatcherScenarioDataStoreBase.cs (100%) rename src/{LogoFX.Client.Core.Specs/Common => LogoFX.Client.Core.Specs.Common}/InvocationScenarioDataStoreBase.cs (100%) create mode 100644 src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj create mode 100644 src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs rename src/{LogoFX.Client.Core.Specs/Common => LogoFX.Client.Core.Specs.Common}/TestClass.cs (100%) create mode 100644 src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs rename src/{LogoFX.Client.Core.Specs/Common => LogoFX.Client.Core.Specs.Common}/TestClassHelper.cs (88%) rename src/{LogoFX.Client.Core.Specs/Common => LogoFX.Client.Core.Specs.Common}/ValueWrapper.cs (100%) delete mode 100644 src/LogoFX.Client.Core.Specs/Common/TestClassFactory.cs diff --git a/appveyor.yml b/appveyor.yml index 195a3f9..0098261 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.2.4.{build} +version: 2.2.5.{build} init: - dotnet tool install --global SpecFlow.Plus.LivingDoc.CLI configuration: Release diff --git a/devops/deploy/deploy-all.bat b/devops/deploy/deploy-all.bat index aa50654..bf84b64 100644 --- a/devops/deploy/deploy-all.bat +++ b/devops/deploy/deploy-all.bat @@ -1,5 +1,5 @@ rem TODO: Use common source for all version instances -SET version=2.2.4 +SET version=2.2.5-rc1 rem TODO: Refactor using loop and automatic discovery call deploy-single.bat LogoFX.Core %version% call deploy-single.bat LogoFX.Practices.IoC %version% diff --git a/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec b/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec index b69e51e..e5079b6 100644 --- a/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec +++ b/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Core.Core - 2.2.4 + 2.2.5-rc1 LogoFX.Client.Core.Core Gennady Verdel, David Kossoglyad, Vlad Spivak Gennady Verdel @@ -14,7 +14,7 @@ LogoFX Client Core Core containing core facilities for client applications development, including implementation of INotifyPropertyChanged and ambient context for the dispatcher. Added SetProperty functionality - + framework logofx dotnet diff --git a/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec b/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec index 43b7d20..f921799 100644 --- a/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec +++ b/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Core - 2.2.4 + 2.2.5-rc1 LogoFX.Client.Core Gennady Verdel, David Kossoglyad, Vlad Spivak Gennady Verdel @@ -14,7 +14,7 @@ LogoFX Client Core containing platform-specific utilities for client applications, including dispatcher. Added .NET 5 support - + framework logofx dotnet diff --git a/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec b/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec index 7b4fb38..ae1d13a 100644 --- a/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec +++ b/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Modularity - 2.2.4 + 2.2.5-rc1 LogoFX.Client.Modularity Gennady Verdel, David Kossoglyad, Dmitry Bublik Gennady Verdel @@ -15,7 +15,7 @@ - + framework logofx dotnet diff --git a/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec b/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec index 81d15e7..c48bc21 100644 --- a/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec +++ b/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Theming - 2.2.4 + 2.2.5-rc1 LogoFX.Client.Theming Dmitry Bublik, David Kossoglyad, Gennady Verdel Gennady Verdel diff --git a/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec b/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec index 688adca..da20e2f 100644 --- a/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec +++ b/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec @@ -2,7 +2,7 @@ LogoFX.Core - 2.2.4 + 2.2.5-rc1 Gennady Verdel, David Kossoglyad, Vlad Spivak, Dmitry Bublik Gennady Verdel false diff --git a/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec b/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec index b36faec..821be97 100644 --- a/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec +++ b/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec @@ -2,7 +2,7 @@ LogoFX.Practices.IoC - 2.2.4 + 2.2.5-rc1 LogoFX.Practices.IoC Gennady Verdel, David Kossoglyad, Dmitry Bublik, Vlad Spivak Gennady Verdel @@ -15,8 +15,8 @@ - - + + framework logofx dotnet diff --git a/devops/publish/publish-all.bat b/devops/publish/publish-all.bat index b2a58e4..e4b50ac 100644 --- a/devops/publish/publish-all.bat +++ b/devops/publish/publish-all.bat @@ -2,7 +2,7 @@ cd ../../src nuget restore cd ../devops/publish PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '../build/build-all.ps1'" -SET package_version=2.2.4 +SET package_version=2.2.5-rc1 cd ../test call test-all cd ../pack diff --git a/devops/publish/publish-single.bat b/devops/publish/publish-single.bat index 66e2280..193afae 100644 --- a/devops/publish/publish-single.bat +++ b/devops/publish/publish-single.bat @@ -1,5 +1,5 @@ SET package_name=%1 -SET package_version=2.2.4 +SET package_version=2.2.5-rc1 SET target=../../../../packages/Tests-All cd ../build call build-all diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature b/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature index d347a2d..73de7f1 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature @@ -5,6 +5,6 @@ Scenario: Changing single property with custom action invocation should invoke actions via custom route Given The dispatcher is set to custom dispatcher - When The 'TestCustomActionInvocationClass' is created here with dispatcher + When The 'TestCustomActionInvocationClass' is created with dispatcher And The number is changed to 5 via SetProperty API Then The property change notification is raised via the custom action invocation diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature.cs b/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature.cs index c9e7683..b5e2d35 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature.cs +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/Invocation.feature.cs @@ -116,7 +116,7 @@ public virtual void ChangingSinglePropertyWithCustomActionInvocationShouldInvoke testRunner.Given("The dispatcher is set to custom dispatcher", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden #line 8 - testRunner.When("The \'TestCustomActionInvocationClass\' is created here with dispatcher", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); + testRunner.When("The \'TestCustomActionInvocationClass\' is created with dispatcher", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden #line 9 testRunner.And("The number is changed to 5 via SetProperty API", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs b/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs index 168192c..1334daa 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs @@ -26,10 +26,11 @@ public void GivenTheDispatcherIsSetToCustomDispatcher() } //TODO: Merge with the same class in LogoFX.Client.Core.Specs - pay attention to different dispatcher types - [When(@"The '(.*)' is created here with dispatcher")] - public void WhenTheIsCreatedHereWithParameter(string name) + //Use Step Argument Transformation - context-dependent + [When(@"The '(.*)' is created with dispatcher")] + public void WhenTheIsCreatedWithDispatcher(string name) { - var @class = TestClassHelper.CreateTestClassImpl(Assembly.GetExecutingAssembly(), name, + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name, _dispatcherScenarioDataStoreBase.Dispatch); if (@class != null) { diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/LogoFX.Client.Core.Platform.NETCore.Specs.csproj b/src/LogoFX.Client.Core.Platform.NETCore.Specs/LogoFX.Client.Core.Platform.NETCore.Specs.csproj index 625070a..af2321f 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/LogoFX.Client.Core.Platform.NETCore.Specs.csproj +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/LogoFX.Client.Core.Platform.NETCore.Specs.csproj @@ -8,10 +8,10 @@ - + - - + + all @@ -20,7 +20,7 @@ - + diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/specflow.json b/src/LogoFX.Client.Core.Platform.NETCore.Specs/specflow.json index 3085e29..5ae2cea 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/specflow.json +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/specflow.json @@ -12,7 +12,7 @@ "plugins": [], "stepAssemblies": [ { - "assembly": "LogoFX.Client.Core.Specs" + "assembly": "LogoFX.Client.Core.Specs.Common" } ] } diff --git a/src/LogoFX.Client.Core.Platform/android/Properties/AssemblyInfo.cs b/src/LogoFX.Client.Core.Platform/android/Properties/AssemblyInfo.cs index 362edf1..4fe817e 100644 --- a/src/LogoFX.Client.Core.Platform/android/Properties/AssemblyInfo.cs +++ b/src/LogoFX.Client.Core.Platform/android/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("2.2.4")] -[assembly: AssemblyFileVersion("2.2.4")] +[assembly: AssemblyVersion("2.2.5")] +[assembly: AssemblyFileVersion("2.2.5")] diff --git a/src/LogoFX.Client.Core.Platform/android/Resources/Resource.Designer.cs b/src/LogoFX.Client.Core.Platform/android/Resources/Resource.Designer.cs index aaec977..42b5827 100644 --- a/src/LogoFX.Client.Core.Platform/android/Resources/Resource.Designer.cs +++ b/src/LogoFX.Client.Core.Platform/android/Resources/Resource.Designer.cs @@ -14,7 +14,7 @@ namespace LogoFX.Client.Core { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "12.1.0.11")] public partial class Resource { diff --git a/src/LogoFX.Client.Core.Platform/iOS/Properties/AssemblyInfo.cs b/src/LogoFX.Client.Core.Platform/iOS/Properties/AssemblyInfo.cs index 9dcaa2e..e49d12f 100644 --- a/src/LogoFX.Client.Core.Platform/iOS/Properties/AssemblyInfo.cs +++ b/src/LogoFX.Client.Core.Platform/iOS/Properties/AssemblyInfo.cs @@ -28,5 +28,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("2.2.4")] -[assembly: AssemblyFileVersion("2.2.4")] +[assembly: AssemblyVersion("2.2.5")] +[assembly: AssemblyFileVersion("2.2.5")] diff --git a/src/LogoFX.Client.Core.Platform/net/LogoFX.Client.Core.Platform.NET.csproj b/src/LogoFX.Client.Core.Platform/net/LogoFX.Client.Core.Platform.NET.csproj index 3493872..07f5f66 100644 --- a/src/LogoFX.Client.Core.Platform/net/LogoFX.Client.Core.Platform.NET.csproj +++ b/src/LogoFX.Client.Core.Platform/net/LogoFX.Client.Core.Platform.NET.csproj @@ -1,11 +1,11 @@ - net5.0-windows + net6.0-windows false LogoFX.Client.Core.Platform LogoFX.Client.Core true - 2.2.4 + 2.2.5 ..\..\Bin\net\Release diff --git a/src/LogoFX.Client.Core.Platform/netcore/LogoFX.Client.Core.Platform.NETCore.csproj b/src/LogoFX.Client.Core.Platform/netcore/LogoFX.Client.Core.Platform.NETCore.csproj index d898b4f..6904444 100644 --- a/src/LogoFX.Client.Core.Platform/netcore/LogoFX.Client.Core.Platform.NETCore.csproj +++ b/src/LogoFX.Client.Core.Platform/netcore/LogoFX.Client.Core.Platform.NETCore.csproj @@ -5,7 +5,7 @@ LogoFX.Client.Core.Platform LogoFX.Client.Core true - 2.2.4 + 2.2.5 ..\..\Bin\netcore\Release diff --git a/src/LogoFX.Client.Core.Platform/netframework/Properties/AssemblyInfo.cs b/src/LogoFX.Client.Core.Platform/netframework/Properties/AssemblyInfo.cs index 535bd1f..0320ab2 100644 --- a/src/LogoFX.Client.Core.Platform/netframework/Properties/AssemblyInfo.cs +++ b/src/LogoFX.Client.Core.Platform/netframework/Properties/AssemblyInfo.cs @@ -28,5 +28,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("2.2.4")] -[assembly: AssemblyFileVersion("2.2.4")] +[assembly: AssemblyVersion("2.2.5")] +[assembly: AssemblyFileVersion("2.2.5")] diff --git a/src/LogoFX.Client.Core.Platform/uwp/Properties/AssemblyInfo.cs b/src/LogoFX.Client.Core.Platform/uwp/Properties/AssemblyInfo.cs index 0cee6a8..561df01 100644 --- a/src/LogoFX.Client.Core.Platform/uwp/Properties/AssemblyInfo.cs +++ b/src/LogoFX.Client.Core.Platform/uwp/Properties/AssemblyInfo.cs @@ -20,6 +20,6 @@ // Build Number // Revision // -[assembly: AssemblyVersion("2.2.4")] -[assembly: AssemblyFileVersion("2.2.4")] +[assembly: AssemblyVersion("2.2.5")] +[assembly: AssemblyFileVersion("2.2.5")] [assembly: ComVisible(false)] diff --git a/src/LogoFX.Client.Core.Specs/Common/DispatcherScenarioDataStoreBase.cs b/src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStoreBase.cs similarity index 100% rename from src/LogoFX.Client.Core.Specs/Common/DispatcherScenarioDataStoreBase.cs rename to src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStoreBase.cs diff --git a/src/LogoFX.Client.Core.Specs/Common/InvocationScenarioDataStoreBase.cs b/src/LogoFX.Client.Core.Specs.Common/InvocationScenarioDataStoreBase.cs similarity index 100% rename from src/LogoFX.Client.Core.Specs/Common/InvocationScenarioDataStoreBase.cs rename to src/LogoFX.Client.Core.Specs.Common/InvocationScenarioDataStoreBase.cs diff --git a/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj b/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj new file mode 100644 index 0000000..8109cdf --- /dev/null +++ b/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.0 + false + false + + + + 8 + + + + 8 + + + + + + + + + + + diff --git a/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs b/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs new file mode 100644 index 0000000..3ee5508 --- /dev/null +++ b/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs @@ -0,0 +1,29 @@ +using TechTalk.SpecFlow; + +namespace LogoFX.Client.Core.Specs.Common +{ + [Binding] + internal sealed class NumberChangeSteps + { + private readonly InvocationScenarioDataStoreBase _invocationScenarioDataStoreBase; + + public NumberChangeSteps(ScenarioContext scenarioContext) + { + _invocationScenarioDataStoreBase = new InvocationScenarioDataStoreBase(scenarioContext); + } + + [When(@"The number is changed to (.*) in regular mode")] + public void WhenTheNumberIsChangedToInRegularMode(int value) + { + var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; + @class.Number = value; + } + + [When(@"The number is changed to (.*) via SetProperty API")] + public void WhenTheNumberIsChangedToViaSetPropertyAPI(int value) + { + var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; + @class.Number = value; + } + } +} diff --git a/src/LogoFX.Client.Core.Specs/Common/TestClass.cs b/src/LogoFX.Client.Core.Specs.Common/TestClass.cs similarity index 100% rename from src/LogoFX.Client.Core.Specs/Common/TestClass.cs rename to src/LogoFX.Client.Core.Specs.Common/TestClass.cs diff --git a/src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs b/src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs new file mode 100644 index 0000000..56d569c --- /dev/null +++ b/src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs @@ -0,0 +1,13 @@ +using System.ComponentModel; +using System.Reflection; + +namespace LogoFX.Client.Core.Specs.Common +{ + public static class TestClassFactory + { + public static INotifyPropertyChanged CreateTestClass(Assembly assembly, string name, params object?[]? args) + { + return TestClassHelper.CreateTestClassImpl(assembly, name, args); + } + } +} diff --git a/src/LogoFX.Client.Core.Specs/Common/TestClassHelper.cs b/src/LogoFX.Client.Core.Specs.Common/TestClassHelper.cs similarity index 88% rename from src/LogoFX.Client.Core.Specs/Common/TestClassHelper.cs rename to src/LogoFX.Client.Core.Specs.Common/TestClassHelper.cs index 81e13c2..b1687d0 100644 --- a/src/LogoFX.Client.Core.Specs/Common/TestClassHelper.cs +++ b/src/LogoFX.Client.Core.Specs.Common/TestClassHelper.cs @@ -9,13 +9,6 @@ namespace LogoFX.Client.Core.Specs.Common { public static class TestClassHelper { - public static INotifyPropertyChanged CreateTestClassImpl(Assembly assembly, string name, params object?[]? args) - { - var types = assembly.DefinedTypes.ToArray(); - var type = types.FirstOrDefault(t => t.Name == name)?.AsType(); - return type == null ? null : Activator.CreateInstance(type, args) as INotifyPropertyChanged; - } - public static ValueWrapper ListenToPropertyChange(INotifyPropertyChanged @class, string propertyName) { var isCalled = false; @@ -29,5 +22,12 @@ public static ValueWrapper ListenToPropertyChange(INotifyPropertyChanged @class, }; return isCalledRef; } + + internal static INotifyPropertyChanged CreateTestClassImpl(Assembly assembly, string name, params object?[]? args) + { + var types = assembly.DefinedTypes.ToArray(); + var type = types.FirstOrDefault(t => t.Name == name)?.AsType(); + return type == null ? null : Activator.CreateInstance(type, args) as INotifyPropertyChanged; + } } } \ No newline at end of file diff --git a/src/LogoFX.Client.Core.Specs/Common/ValueWrapper.cs b/src/LogoFX.Client.Core.Specs.Common/ValueWrapper.cs similarity index 100% rename from src/LogoFX.Client.Core.Specs/Common/ValueWrapper.cs rename to src/LogoFX.Client.Core.Specs.Common/ValueWrapper.cs diff --git a/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs b/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs index 5a6326e..54a4e87 100644 --- a/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs +++ b/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs @@ -1,10 +1,11 @@ -using LogoFX.Client.Core.Specs.Dispatcher; +using System.Reflection; +using LogoFX.Client.Core.Specs.Dispatcher; using TechTalk.SpecFlow; namespace LogoFX.Client.Core.Specs.Common { [Binding] - internal sealed class CommonSteps + public sealed class CommonSteps { private readonly DispatcherScenarioDataStoreBase _dispatcherScenarioDataStoreBase; private readonly InvocationScenarioDataStoreBase _invocationScenarioDataStoreBase; @@ -18,7 +19,7 @@ public CommonSteps(ScenarioContext scenarioContext) [When(@"The '(.*)' is created")] public void WhenTheIsCreated(string name) { - var @class = TestClassFactory.CreateTestClass(name); + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name); if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Number"); @@ -30,7 +31,7 @@ public void WhenTheIsCreated(string name) [When(@"The '(.*)' is created with dispatcher")] public void WhenTheIsCreatedWithDispatcher(string name) { - var @class = TestClassFactory.CreateTestClass(name, _dispatcherScenarioDataStoreBase.Dispatch); + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name, _dispatcherScenarioDataStoreBase.Dispatch); if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Number"); @@ -42,7 +43,7 @@ public void WhenTheIsCreatedWithDispatcher(string name) [When(@"The '(.*)' is created and empty notification is listened to")] public void WhenTheIsCreatedAndEmptyNotificationIsListenedTo(string name) { - var @class = TestClassFactory.CreateTestClass(name); + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name); if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, string.Empty); @@ -51,20 +52,6 @@ public void WhenTheIsCreatedAndEmptyNotificationIsListenedTo(string name) } } - [When(@"The number is changed to (.*) in regular mode")] - public void WhenTheNumberIsChangedToInRegularMode(int value) - { - var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; - @class.Number = value; - } - - [When(@"The number is changed to (.*) via SetProperty API")] - public void WhenTheNumberIsChangedToViaSetPropertyAPI(int value) - { - var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; - @class.Number = value; - } - [When(@"The all properties change is invoked")] public void WhenTheAllPropertiesChangeIsInvoked() { @@ -72,4 +59,4 @@ public void WhenTheAllPropertiesChangeIsInvoked() @class.Refresh(); } } -} +} \ No newline at end of file diff --git a/src/LogoFX.Client.Core.Specs/Common/TestClassFactory.cs b/src/LogoFX.Client.Core.Specs/Common/TestClassFactory.cs deleted file mode 100644 index 54fbe84..0000000 --- a/src/LogoFX.Client.Core.Specs/Common/TestClassFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ComponentModel; -using System.Reflection; - -namespace LogoFX.Client.Core.Specs.Common -{ - internal static class TestClassFactory - { - internal static INotifyPropertyChanged CreateTestClass(string name, params object?[]? args) - { - return TestClassHelper.CreateTestClassImpl(Assembly.GetExecutingAssembly(), name, args); - } - } -} diff --git a/src/LogoFX.Client.Core.Specs/LogoFX.Client.Core.Specs.csproj b/src/LogoFX.Client.Core.Specs/LogoFX.Client.Core.Specs.csproj index 827d00e..cfd59fe 100644 --- a/src/LogoFX.Client.Core.Specs/LogoFX.Client.Core.Specs.csproj +++ b/src/LogoFX.Client.Core.Specs/LogoFX.Client.Core.Specs.csproj @@ -1,17 +1,17 @@ - netcoreapp3.1 + net6.0 false false - + - + - - + + all @@ -27,6 +27,7 @@ + \ No newline at end of file diff --git a/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs b/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs index 037e46b..20c94f8 100644 --- a/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs +++ b/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; +using System.Reflection; using FluentAssertions; using LogoFX.Client.Core.Specs.Common; using TechTalk.SpecFlow; @@ -38,7 +39,7 @@ public void WhenTheQuantityIsChangedToViaSetPropertyAPI(int value) [When(@"The '(.*)' is created and all notifications are listened to")] public void WhenTheIsCreatedAndAllNotificationsAreListenedTo(string name) { - var @class = TestClassFactory.CreateTestClass(name); + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name); if (@class != null) { _invocationScenarioDataStoreBase.Class = @class; diff --git a/src/LogoFX.Client.Core.Specs/specflow.json b/src/LogoFX.Client.Core.Specs/specflow.json index e21dfe4..3c119b5 100644 --- a/src/LogoFX.Client.Core.Specs/specflow.json +++ b/src/LogoFX.Client.Core.Specs/specflow.json @@ -1,13 +1,18 @@ { - "bindingCulture": { - "language": "en-us" - }, - "language": { - "feature": "en-us" - }, - "livingDocGenerator": { - "enabled": true, - "filePath": "TestExecution.json" - }, - "plugins": [] + "bindingCulture": { + "language": "en-us" + }, + "language": { + "feature": "en-us" + }, + "livingDocGenerator": { + "enabled": true, + "filePath": "TestExecution.json" + }, + "plugins":[], + "stepAssemblies": [ + { + "assembly": "LogoFX.Client.Core.Specs.Common" + } + ] } \ No newline at end of file diff --git a/src/LogoFX.Client.Core/LogoFX.Client.Core.csproj b/src/LogoFX.Client.Core/LogoFX.Client.Core.csproj index 834493c..7cccf8a 100644 --- a/src/LogoFX.Client.Core/LogoFX.Client.Core.csproj +++ b/src/LogoFX.Client.Core/LogoFX.Client.Core.csproj @@ -2,7 +2,7 @@ netstandard2.0 false - 2.2.4 + 2.2.5 ..\Bin\netstandard\Release diff --git a/src/LogoFX.Client.Modularity/LogoFX.Client.Modularity.csproj b/src/LogoFX.Client.Modularity/LogoFX.Client.Modularity.csproj index 2e24b72..87f4a00 100644 --- a/src/LogoFX.Client.Modularity/LogoFX.Client.Modularity.csproj +++ b/src/LogoFX.Client.Modularity/LogoFX.Client.Modularity.csproj @@ -2,7 +2,7 @@ netstandard2.0 false - 2.2.4 + 2.2.5 ..\Bin\netstandard\Release @@ -12,6 +12,6 @@ true - + \ No newline at end of file diff --git a/src/LogoFX.Client.Theming.Platform/net/LogoFX.Client.Theming.Platform.NET.csproj b/src/LogoFX.Client.Theming.Platform/net/LogoFX.Client.Theming.Platform.NET.csproj index 8e96eb1..938735c 100644 --- a/src/LogoFX.Client.Theming.Platform/net/LogoFX.Client.Theming.Platform.NET.csproj +++ b/src/LogoFX.Client.Theming.Platform/net/LogoFX.Client.Theming.Platform.NET.csproj @@ -1,11 +1,11 @@ - net5.0-windows + net6.0-windows false true LogoFX.Client.Theming.Platform LogoFX.Client.Theming - 2.2.4 + 2.2.5 ..\..\bin\net\Release diff --git a/src/LogoFX.Client.Theming.Platform/netcore/LogoFX.Client.Theming.Platform.NETCore.csproj b/src/LogoFX.Client.Theming.Platform/netcore/LogoFX.Client.Theming.Platform.NETCore.csproj index 81fdead..13ea0ad 100644 --- a/src/LogoFX.Client.Theming.Platform/netcore/LogoFX.Client.Theming.Platform.NETCore.csproj +++ b/src/LogoFX.Client.Theming.Platform/netcore/LogoFX.Client.Theming.Platform.NETCore.csproj @@ -5,7 +5,7 @@ true LogoFX.Client.Theming.Platform LogoFX.Client.Theming - 2.2.4 + 2.2.5 ..\..\bin\netcore\Release diff --git a/src/LogoFX.Client.Theming.Platform/netframework/Properties/AssemblyInfo.cs b/src/LogoFX.Client.Theming.Platform/netframework/Properties/AssemblyInfo.cs index 0db9468..e07ff6e 100644 --- a/src/LogoFX.Client.Theming.Platform/netframework/Properties/AssemblyInfo.cs +++ b/src/LogoFX.Client.Theming.Platform/netframework/Properties/AssemblyInfo.cs @@ -44,5 +44,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("2.2.4")] -[assembly: AssemblyFileVersion("2.2.4")] +[assembly: AssemblyVersion("2.2.5")] +[assembly: AssemblyFileVersion("2.2.5")] diff --git a/src/LogoFX.Client.Theming/LogoFX.Client.Theming.csproj b/src/LogoFX.Client.Theming/LogoFX.Client.Theming.csproj index b900fa9..13d94f0 100644 --- a/src/LogoFX.Client.Theming/LogoFX.Client.Theming.csproj +++ b/src/LogoFX.Client.Theming/LogoFX.Client.Theming.csproj @@ -2,7 +2,7 @@ netstandard2.0 false - 2.2.4 + 2.2.5 ..\bin\netstandard\Release diff --git a/src/LogoFX.Core.sln b/src/LogoFX.Core.sln index 888d219..4cea4b3 100644 --- a/src/LogoFX.Core.sln +++ b/src/LogoFX.Core.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31613.86 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogoFX.Core", "LogoFX.Core\LogoFX.Core.csproj", "{6490D4C8-1379-4448-96F1-8BAB571C04E8}" EndProject @@ -49,6 +49,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogoFX.Client.Theming.Platf EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogoFX.Client.Theming.Platform.WPF", "LogoFX.Client.Theming.Platform\netframework\LogoFX.Client.Theming.Platform.WPF.csproj", "{3720D35C-1548-4B53-A37D-31A5C7D49A20}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogoFX.Client.Core.Specs.Common", "LogoFX.Client.Core.Specs.Common\LogoFX.Client.Core.Specs.Common.csproj", "{728663E9-62A0-4482-8F0A-832699835760}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -365,6 +367,22 @@ Global {3720D35C-1548-4B53-A37D-31A5C7D49A20}.Release|x64.Build.0 = Release|Any CPU {3720D35C-1548-4B53-A37D-31A5C7D49A20}.Release|x86.ActiveCfg = Release|Any CPU {3720D35C-1548-4B53-A37D-31A5C7D49A20}.Release|x86.Build.0 = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|Any CPU.Build.0 = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|ARM.ActiveCfg = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|ARM.Build.0 = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|x64.ActiveCfg = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|x64.Build.0 = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|x86.ActiveCfg = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Debug|x86.Build.0 = Debug|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|Any CPU.ActiveCfg = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|Any CPU.Build.0 = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|ARM.ActiveCfg = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|ARM.Build.0 = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|x64.ActiveCfg = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|x64.Build.0 = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|x86.ActiveCfg = Release|Any CPU + {728663E9-62A0-4482-8F0A-832699835760}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -389,6 +407,7 @@ Global {0CAE2C6B-7608-426D-A66A-7B642438EA08} = {61BF3ACA-38BF-4273-B93A-732FB0D08CED} {C802E723-0E2D-49AC-81CE-D435C8303F48} = {61BF3ACA-38BF-4273-B93A-732FB0D08CED} {3720D35C-1548-4B53-A37D-31A5C7D49A20} = {61BF3ACA-38BF-4273-B93A-732FB0D08CED} + {728663E9-62A0-4482-8F0A-832699835760} = {F555D153-CB40-4452-B5E4-E9731566272E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AC15861E-3935-4FBC-AA56-C0C4CFF71FC3} diff --git a/src/LogoFX.Core/LogoFX.Core.csproj b/src/LogoFX.Core/LogoFX.Core.csproj index bf522dd..c5d8bac 100644 --- a/src/LogoFX.Core/LogoFX.Core.csproj +++ b/src/LogoFX.Core/LogoFX.Core.csproj @@ -2,7 +2,7 @@ netstandard2.0 false - 2.2.4 + 2.2.5 Gennady Verdel, David Kossoglyad, Vlad Spivak, Dmitry Bublik LogoFX LogoFX Core assemblies containing collections and weak objects implementations. diff --git a/src/LogoFX.Practices.IoC.Modularity/LogoFX.Practices.IoC.Modularity.csproj b/src/LogoFX.Practices.IoC.Modularity/LogoFX.Practices.IoC.Modularity.csproj index e09b65c..61a6cf6 100644 --- a/src/LogoFX.Practices.IoC.Modularity/LogoFX.Practices.IoC.Modularity.csproj +++ b/src/LogoFX.Practices.IoC.Modularity/LogoFX.Practices.IoC.Modularity.csproj @@ -2,7 +2,7 @@ netstandard2.0 false - 2.2.4 + 2.2.5 ..\Bin\netstandard\Release @@ -12,7 +12,7 @@ true - + diff --git a/src/LogoFX.Practices.IoC.Specs/LogoFX.Practices.IoC.Specs.csproj b/src/LogoFX.Practices.IoC.Specs/LogoFX.Practices.IoC.Specs.csproj index b3da4f9..9c51029 100644 --- a/src/LogoFX.Practices.IoC.Specs/LogoFX.Practices.IoC.Specs.csproj +++ b/src/LogoFX.Practices.IoC.Specs/LogoFX.Practices.IoC.Specs.csproj @@ -1,17 +1,17 @@ - netcoreapp3.1 + net6.0 false false - + - + - - + + all diff --git a/src/LogoFX.Practices.IoC/LogoFX.Practices.IoC.csproj b/src/LogoFX.Practices.IoC/LogoFX.Practices.IoC.csproj index 621273e..6b98d37 100644 --- a/src/LogoFX.Practices.IoC/LogoFX.Practices.IoC.csproj +++ b/src/LogoFX.Practices.IoC/LogoFX.Practices.IoC.csproj @@ -2,7 +2,7 @@ netstandard2.0 false - 2.2.4 + 2.2.5 ..\Bin\netstandard\Release From cf7b14ba4e1b2499c626045cc43e786bd9307b64 Mon Sep 17 00:00:00 2001 From: Gennady Verdel Date: Wed, 24 Nov 2021 18:41:48 +0200 Subject: [PATCH 2/3] devops: using VS2022 image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 0098261..429f242 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ after_test: - cd devops - cd pack - pack-all -image: Visual Studio 2019 +image: Visual Studio 2022 artifacts: - name: Packages path: ./output/*.nupkg From 7e964a378fc890e93338f83d2db99f09b2795409 Mon Sep 17 00:00:00 2001 From: Gennady Verdel Date: Sun, 5 Dec 2021 19:39:32 +0200 Subject: [PATCH 3/3] feat(inpc): added set property support for NotifyPropertyChangedCore #6 (#7) * feat(inpc): added set property support for NotifyPropertyChangedCore #6 * chore: bump version to 2.2.5 --- README.md | 2 +- devops/deploy/deploy-all.bat | 2 +- .../contents/LogoFX.Client.Core.Core.nuspec | 4 +- .../contents/LogoFX.Client.Core.nuspec | 4 +- .../contents/LogoFX.Client.Modularity.nuspec | 2 +- .../contents/LogoFX.Client.Theming.nuspec | 2 +- .../LogoFX.Core/contents/LogoFX.Core.nuspec | 2 +- .../contents/LogoFX.Practices.IoC.nuspec | 4 +- devops/publish/publish-all.bat | 2 +- devops/publish/publish-single.bat | 2 +- devops/test/test-all.bat | 1 + .../InvocationSteps.cs | 21 +- .../TestCustomActionInvocationClass.cs | 1 + ...Base.cs => DispatcherScenarioDataStore.cs} | 4 +- .../LogoFX.Client.Core.Specs.Common.csproj | 15 +- .../NumberChangeSteps.cs | 11 +- .../{TestClass.cs => TestClassBase.cs} | 0 .../TestClassFactory.cs | 13 - .../Common/CommonSteps.cs | 26 +- .../Common/LifecycleHook.cs | 1 - .../Common/TestAfterValueUpdateClass.cs | 2 + .../Common/TestBeforeValueUpdateClass.cs | 2 + .../Common/TestMultipleClass.cs | 2 + .../Dispatcher/DispatcherSteps.cs | 14 +- .../ImplicitUsings.cs | 2 + .../NotifyPropertyChangedSteps.cs | 29 +- ...eBase.cs => SemaphoreScenarioDataStore.cs} | 5 +- .../Semaphore/SemaphoreSteps.cs | 19 +- src/LogoFX.Client.Core.Specs/specflow.json | 3 + .../NotifyPropertyChangedCore.cs | 72 ---- src/LogoFX.Core.Specs.Common/CommonSteps.cs | 24 ++ .../InvocationScenarioDataStore.cs} | 6 +- .../LogoFX.Core.Specs.Common.csproj | 17 + .../TestClassFactory.cs | 17 + .../TestClassHelper.cs | 12 +- .../ValueWrapper.cs | 2 +- src/LogoFX.Core.Specs/CommonSteps.cs | 28 ++ src/LogoFX.Core.Specs/ImplicitUsings.cs | 2 + .../LogoFX.Core.Specs.csproj | 36 ++ src/LogoFX.Core.Specs/Notification.feature | 40 +++ src/LogoFX.Core.Specs/Notification.feature.cs | 326 ++++++++++++++++++ .../NotifyPropertyChangedSteps.cs | 29 ++ src/LogoFX.Core.Specs/NumberChangeSteps.cs | 39 +++ .../TestAfterValueUpdateClass.cs | 21 ++ .../TestBeforeValueUpdateClass.cs | 24 ++ src/LogoFX.Core.Specs/TestClassBase.cs | 28 ++ src/LogoFX.Core.Specs/TestExpressionClass.cs | 22 ++ src/LogoFX.Core.Specs/TestNameClass.cs | 22 ++ src/LogoFX.Core.Specs/TestRegularClass.cs | 18 + src/LogoFX.Core.Specs/specflow.json | 18 + src/LogoFX.Core.Specs/xunit.runner.json | 4 + src/LogoFX.Core.sln | 40 ++- src/LogoFX.Core/NotifyPropertyChangedCore.cs | 147 ++++++++ .../PropertyChangedEventHandlerExtensions.cs | 3 +- .../PropertyChangedExtensions.cs | 3 +- .../SetPropertyOptions.cs | 3 +- ...eBase.cs => ContainerScenarioDataStore.cs} | 4 +- .../ExtendedSimpleContainerSteps.cs | 40 +-- 58 files changed, 1023 insertions(+), 221 deletions(-) rename src/LogoFX.Client.Core.Specs.Common/{DispatcherScenarioDataStoreBase.cs => DispatcherScenarioDataStore.cs} (60%) rename src/LogoFX.Client.Core.Specs.Common/{TestClass.cs => TestClassBase.cs} (100%) delete mode 100644 src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs create mode 100644 src/LogoFX.Client.Core.Specs/ImplicitUsings.cs rename src/LogoFX.Client.Core.Specs/Semaphore/{SemaphoreScenarioDataStoreBase.cs => SemaphoreScenarioDataStore.cs} (56%) delete mode 100644 src/LogoFX.Client.Core/NotifyPropertyChangedCore.cs create mode 100644 src/LogoFX.Core.Specs.Common/CommonSteps.cs rename src/{LogoFX.Client.Core.Specs.Common/InvocationScenarioDataStoreBase.cs => LogoFX.Core.Specs.Common/InvocationScenarioDataStore.cs} (73%) create mode 100644 src/LogoFX.Core.Specs.Common/LogoFX.Core.Specs.Common.csproj create mode 100644 src/LogoFX.Core.Specs.Common/TestClassFactory.cs rename src/{LogoFX.Client.Core.Specs.Common => LogoFX.Core.Specs.Common}/TestClassHelper.cs (54%) rename src/{LogoFX.Client.Core.Specs.Common => LogoFX.Core.Specs.Common}/ValueWrapper.cs (79%) create mode 100644 src/LogoFX.Core.Specs/CommonSteps.cs create mode 100644 src/LogoFX.Core.Specs/ImplicitUsings.cs create mode 100644 src/LogoFX.Core.Specs/LogoFX.Core.Specs.csproj create mode 100644 src/LogoFX.Core.Specs/Notification.feature create mode 100644 src/LogoFX.Core.Specs/Notification.feature.cs create mode 100644 src/LogoFX.Core.Specs/NotifyPropertyChangedSteps.cs create mode 100644 src/LogoFX.Core.Specs/NumberChangeSteps.cs create mode 100644 src/LogoFX.Core.Specs/TestAfterValueUpdateClass.cs create mode 100644 src/LogoFX.Core.Specs/TestBeforeValueUpdateClass.cs create mode 100644 src/LogoFX.Core.Specs/TestClassBase.cs create mode 100644 src/LogoFX.Core.Specs/TestExpressionClass.cs create mode 100644 src/LogoFX.Core.Specs/TestNameClass.cs create mode 100644 src/LogoFX.Core.Specs/TestRegularClass.cs create mode 100644 src/LogoFX.Core.Specs/specflow.json create mode 100644 src/LogoFX.Core.Specs/xunit.runner.json create mode 100644 src/LogoFX.Core/NotifyPropertyChangedCore.cs rename src/{LogoFX.Client.Core => LogoFX.Core}/PropertyChangedEventHandlerExtensions.cs (99%) rename src/{LogoFX.Client.Core => LogoFX.Core}/PropertyChangedExtensions.cs (99%) rename src/{LogoFX.Client.Core => LogoFX.Core}/SetPropertyOptions.cs (96%) rename src/LogoFX.Practices.IoC.Specs/{ContainerScenarioDataStoreBase.cs => ContainerScenarioDataStore.cs} (82%) diff --git a/README.md b/README.md index d2633e9..7b34148 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Core facilties +# Core facilities diff --git a/devops/deploy/deploy-all.bat b/devops/deploy/deploy-all.bat index bf84b64..844c347 100644 --- a/devops/deploy/deploy-all.bat +++ b/devops/deploy/deploy-all.bat @@ -1,5 +1,5 @@ rem TODO: Use common source for all version instances -SET version=2.2.5-rc1 +SET version=2.2.5 rem TODO: Refactor using loop and automatic discovery call deploy-single.bat LogoFX.Core %version% call deploy-single.bat LogoFX.Practices.IoC %version% diff --git a/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec b/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec index e5079b6..b7cbc19 100644 --- a/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec +++ b/devops/pack/LogoFX.Client.Core.Core/contents/LogoFX.Client.Core.Core.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Core.Core - 2.2.5-rc1 + 2.2.5 LogoFX.Client.Core.Core Gennady Verdel, David Kossoglyad, Vlad Spivak Gennady Verdel @@ -14,7 +14,7 @@ LogoFX Client Core Core containing core facilities for client applications development, including implementation of INotifyPropertyChanged and ambient context for the dispatcher. Added SetProperty functionality - + framework logofx dotnet diff --git a/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec b/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec index f921799..dbf5bce 100644 --- a/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec +++ b/devops/pack/LogoFX.Client.Core/contents/LogoFX.Client.Core.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Core - 2.2.5-rc1 + 2.2.5 LogoFX.Client.Core Gennady Verdel, David Kossoglyad, Vlad Spivak Gennady Verdel @@ -14,7 +14,7 @@ LogoFX Client Core containing platform-specific utilities for client applications, including dispatcher. Added .NET 5 support - + framework logofx dotnet diff --git a/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec b/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec index ae1d13a..e357626 100644 --- a/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec +++ b/devops/pack/LogoFX.Client.Modularity/contents/LogoFX.Client.Modularity.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Modularity - 2.2.5-rc1 + 2.2.5 LogoFX.Client.Modularity Gennady Verdel, David Kossoglyad, Dmitry Bublik Gennady Verdel diff --git a/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec b/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec index c48bc21..927b519 100644 --- a/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec +++ b/devops/pack/LogoFX.Client.Theming/contents/LogoFX.Client.Theming.nuspec @@ -2,7 +2,7 @@ LogoFX.Client.Theming - 2.2.5-rc1 + 2.2.5 LogoFX.Client.Theming Dmitry Bublik, David Kossoglyad, Gennady Verdel Gennady Verdel diff --git a/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec b/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec index da20e2f..b642fb3 100644 --- a/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec +++ b/devops/pack/LogoFX.Core/contents/LogoFX.Core.nuspec @@ -2,7 +2,7 @@ LogoFX.Core - 2.2.5-rc1 + 2.2.5 Gennady Verdel, David Kossoglyad, Vlad Spivak, Dmitry Bublik Gennady Verdel false diff --git a/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec b/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec index 821be97..ce03138 100644 --- a/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec +++ b/devops/pack/LogoFX.Practices.IoC/contents/LogoFX.Practices.IoC.nuspec @@ -2,7 +2,7 @@ LogoFX.Practices.IoC - 2.2.5-rc1 + 2.2.5 LogoFX.Practices.IoC Gennady Verdel, David Kossoglyad, Dmitry Bublik, Vlad Spivak Gennady Verdel @@ -15,7 +15,7 @@ - + framework logofx dotnet diff --git a/devops/publish/publish-all.bat b/devops/publish/publish-all.bat index e4b50ac..cded31c 100644 --- a/devops/publish/publish-all.bat +++ b/devops/publish/publish-all.bat @@ -2,7 +2,7 @@ cd ../../src nuget restore cd ../devops/publish PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '../build/build-all.ps1'" -SET package_version=2.2.5-rc1 +SET package_version=2.2.5 cd ../test call test-all cd ../pack diff --git a/devops/publish/publish-single.bat b/devops/publish/publish-single.bat index 193afae..ceee6a7 100644 --- a/devops/publish/publish-single.bat +++ b/devops/publish/publish-single.bat @@ -1,5 +1,5 @@ SET package_name=%1 -SET package_version=2.2.5-rc1 +SET package_version=2.2.5 SET target=../../../../packages/Tests-All cd ../build call build-all diff --git a/devops/test/test-all.bat b/devops/test/test-all.bat index 14a598f..86d551f 100644 --- a/devops/test/test-all.bat +++ b/devops/test/test-all.bat @@ -1,4 +1,5 @@ call test-tests-single.bat LogoFX.Core.Tests +call test-specs-single LogoFX.Core.Specs call test-specs-single LogoFX.Client.Core.Specs call test-specs-single LogoFX.Client.Core.Platform.NETCore.Specs call test-specs-single.bat LogoFX.Practices.IoC.Specs diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs b/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs index 1334daa..43cefe7 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/InvocationSteps.cs @@ -2,6 +2,7 @@ using System.Threading; using FluentAssertions; using LogoFX.Client.Core.Specs.Common; +using LogoFX.Core.Specs.Common; using TechTalk.SpecFlow; namespace LogoFX.Client.Core.Platform.NETCore.Specs @@ -9,20 +10,20 @@ namespace LogoFX.Client.Core.Platform.NETCore.Specs [Binding] internal sealed class InvocationSteps { - private readonly DispatcherScenarioDataStoreBase _dispatcherScenarioDataStoreBase; - private readonly InvocationScenarioDataStoreBase _invocationScenarioDataStoreBase; + private readonly DispatcherScenarioDataStore _dispatcherScenarioDataStore; + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; public InvocationSteps(ScenarioContext scenarioContext) { - _dispatcherScenarioDataStoreBase = - new DispatcherScenarioDataStoreBase(scenarioContext); - _invocationScenarioDataStoreBase = new InvocationScenarioDataStoreBase(scenarioContext); + _dispatcherScenarioDataStore = + new DispatcherScenarioDataStore(scenarioContext); + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); } [Given(@"The dispatcher is set to custom dispatcher")] public void GivenTheDispatcherIsSetToCustomDispatcher() { - _dispatcherScenarioDataStoreBase.Dispatch = new TestPlatformDispatch(new PlatformDispatch()); + _dispatcherScenarioDataStore.Dispatch = new TestPlatformDispatch(new PlatformDispatch()); } //TODO: Merge with the same class in LogoFX.Client.Core.Specs - pay attention to different dispatcher types @@ -31,19 +32,19 @@ public void GivenTheDispatcherIsSetToCustomDispatcher() public void WhenTheIsCreatedWithDispatcher(string name) { var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name, - _dispatcherScenarioDataStoreBase.Dispatch); + _dispatcherScenarioDataStore.Dispatch); if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Number"); - _invocationScenarioDataStoreBase.Class = @class; - _invocationScenarioDataStoreBase.IsCalledRef = isCalledRef; + _invocationScenarioDataStore.Class = @class; + _invocationScenarioDataStore.IsCalledRef = isCalledRef; } } [Then(@"The property change notification is raised via the custom action invocation")] public void ThenThePropertyChangeNotificationIsRaisedViaTheCustomActionInvocation() { - var fakeDispatch = _dispatcherScenarioDataStoreBase.Dispatch; + var fakeDispatch = _dispatcherScenarioDataStore.Dispatch; fakeDispatch.IsCustomActionInvoked.Should().BeTrue(); } } diff --git a/src/LogoFX.Client.Core.Platform.NETCore.Specs/TestCustomActionInvocationClass.cs b/src/LogoFX.Client.Core.Platform.NETCore.Specs/TestCustomActionInvocationClass.cs index 7a1bc75..ed18952 100644 --- a/src/LogoFX.Client.Core.Platform.NETCore.Specs/TestCustomActionInvocationClass.cs +++ b/src/LogoFX.Client.Core.Platform.NETCore.Specs/TestCustomActionInvocationClass.cs @@ -1,5 +1,6 @@ using System.Windows.Threading; using LogoFX.Client.Core.Specs.Common; +using LogoFX.Core; namespace LogoFX.Client.Core.Platform.NETCore.Specs { diff --git a/src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStoreBase.cs b/src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStore.cs similarity index 60% rename from src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStoreBase.cs rename to src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStore.cs index 1376249..19810a9 100644 --- a/src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStoreBase.cs +++ b/src/LogoFX.Client.Core.Specs.Common/DispatcherScenarioDataStore.cs @@ -4,9 +4,9 @@ namespace LogoFX.Client.Core.Specs.Common { [Binding] - public sealed class DispatcherScenarioDataStoreBase : ScenarioDataStoreBase + public sealed class DispatcherScenarioDataStore : ScenarioDataStoreBase { - public DispatcherScenarioDataStoreBase(ScenarioContext scenarioContext) : base(scenarioContext) + public DispatcherScenarioDataStore(ScenarioContext scenarioContext) : base(scenarioContext) { } diff --git a/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj b/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj index 8109cdf..94fd7dc 100644 --- a/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj +++ b/src/LogoFX.Client.Core.Specs.Common/LogoFX.Client.Core.Specs.Common.csproj @@ -1,25 +1,20 @@ - - netstandard2.0 - false - false + netstandard2.0 + false + false - 8 - 8 - - + - - + \ No newline at end of file diff --git a/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs b/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs index 3ee5508..21f92e1 100644 --- a/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs +++ b/src/LogoFX.Client.Core.Specs.Common/NumberChangeSteps.cs @@ -1,28 +1,29 @@ -using TechTalk.SpecFlow; +using LogoFX.Core.Specs.Common; +using TechTalk.SpecFlow; namespace LogoFX.Client.Core.Specs.Common { [Binding] internal sealed class NumberChangeSteps { - private readonly InvocationScenarioDataStoreBase _invocationScenarioDataStoreBase; + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; public NumberChangeSteps(ScenarioContext scenarioContext) { - _invocationScenarioDataStoreBase = new InvocationScenarioDataStoreBase(scenarioContext); + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); } [When(@"The number is changed to (.*) in regular mode")] public void WhenTheNumberIsChangedToInRegularMode(int value) { - var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; + var @class = _invocationScenarioDataStore.Class as TestClassBase; @class.Number = value; } [When(@"The number is changed to (.*) via SetProperty API")] public void WhenTheNumberIsChangedToViaSetPropertyAPI(int value) { - var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; + var @class = _invocationScenarioDataStore.Class as TestClassBase; @class.Number = value; } } diff --git a/src/LogoFX.Client.Core.Specs.Common/TestClass.cs b/src/LogoFX.Client.Core.Specs.Common/TestClassBase.cs similarity index 100% rename from src/LogoFX.Client.Core.Specs.Common/TestClass.cs rename to src/LogoFX.Client.Core.Specs.Common/TestClassBase.cs diff --git a/src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs b/src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs deleted file mode 100644 index 56d569c..0000000 --- a/src/LogoFX.Client.Core.Specs.Common/TestClassFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ComponentModel; -using System.Reflection; - -namespace LogoFX.Client.Core.Specs.Common -{ - public static class TestClassFactory - { - public static INotifyPropertyChanged CreateTestClass(Assembly assembly, string name, params object?[]? args) - { - return TestClassHelper.CreateTestClassImpl(assembly, name, args); - } - } -} diff --git a/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs b/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs index 54a4e87..c8bc379 100644 --- a/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs +++ b/src/LogoFX.Client.Core.Specs/Common/CommonSteps.cs @@ -1,19 +1,19 @@ using System.Reflection; using LogoFX.Client.Core.Specs.Dispatcher; -using TechTalk.SpecFlow; +using LogoFX.Core.Specs.Common; namespace LogoFX.Client.Core.Specs.Common { [Binding] public sealed class CommonSteps { - private readonly DispatcherScenarioDataStoreBase _dispatcherScenarioDataStoreBase; - private readonly InvocationScenarioDataStoreBase _invocationScenarioDataStoreBase; + private readonly DispatcherScenarioDataStore _dispatcherScenarioDataStore; + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; public CommonSteps(ScenarioContext scenarioContext) { - _dispatcherScenarioDataStoreBase = new DispatcherScenarioDataStoreBase(scenarioContext); - _invocationScenarioDataStoreBase = new InvocationScenarioDataStoreBase(scenarioContext); + _dispatcherScenarioDataStore = new DispatcherScenarioDataStore(scenarioContext); + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); } [When(@"The '(.*)' is created")] @@ -23,20 +23,20 @@ public void WhenTheIsCreated(string name) if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Number"); - _invocationScenarioDataStoreBase.Class = @class; - _invocationScenarioDataStoreBase.IsCalledRef = isCalledRef; + _invocationScenarioDataStore.Class = @class; + _invocationScenarioDataStore.IsCalledRef = isCalledRef; } } [When(@"The '(.*)' is created with dispatcher")] public void WhenTheIsCreatedWithDispatcher(string name) { - var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name, _dispatcherScenarioDataStoreBase.Dispatch); + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name, _dispatcherScenarioDataStore.Dispatch); if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Number"); - _invocationScenarioDataStoreBase.Class = @class; - _invocationScenarioDataStoreBase.IsCalledRef = isCalledRef; + _invocationScenarioDataStore.Class = @class; + _invocationScenarioDataStore.IsCalledRef = isCalledRef; } } @@ -47,15 +47,15 @@ public void WhenTheIsCreatedAndEmptyNotificationIsListenedTo(string name) if (@class != null) { var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, string.Empty); - _invocationScenarioDataStoreBase.Class = @class; - _invocationScenarioDataStoreBase.IsCalledRef = isCalledRef; + _invocationScenarioDataStore.Class = @class; + _invocationScenarioDataStore.IsCalledRef = isCalledRef; } } [When(@"The all properties change is invoked")] public void WhenTheAllPropertiesChangeIsInvoked() { - var @class = _invocationScenarioDataStoreBase.Class as TestNameClass; + var @class = _invocationScenarioDataStore.Class as TestNameClass; @class.Refresh(); } } diff --git a/src/LogoFX.Client.Core.Specs/Common/LifecycleHook.cs b/src/LogoFX.Client.Core.Specs/Common/LifecycleHook.cs index a688c14..dc84d82 100644 --- a/src/LogoFX.Client.Core.Specs/Common/LifecycleHook.cs +++ b/src/LogoFX.Client.Core.Specs/Common/LifecycleHook.cs @@ -1,5 +1,4 @@ using System.Threading; -using TechTalk.SpecFlow; namespace LogoFX.Client.Core.Specs.Common { diff --git a/src/LogoFX.Client.Core.Specs/Common/TestAfterValueUpdateClass.cs b/src/LogoFX.Client.Core.Specs/Common/TestAfterValueUpdateClass.cs index 3dff037..0c48f49 100644 --- a/src/LogoFX.Client.Core.Specs/Common/TestAfterValueUpdateClass.cs +++ b/src/LogoFX.Client.Core.Specs/Common/TestAfterValueUpdateClass.cs @@ -1,3 +1,5 @@ +using LogoFX.Core; + namespace LogoFX.Client.Core.Specs.Common { public class TestAfterValueUpdateClass : TestClassBase diff --git a/src/LogoFX.Client.Core.Specs/Common/TestBeforeValueUpdateClass.cs b/src/LogoFX.Client.Core.Specs/Common/TestBeforeValueUpdateClass.cs index b6382cc..c45b757 100644 --- a/src/LogoFX.Client.Core.Specs/Common/TestBeforeValueUpdateClass.cs +++ b/src/LogoFX.Client.Core.Specs/Common/TestBeforeValueUpdateClass.cs @@ -1,3 +1,5 @@ +using LogoFX.Core; + namespace LogoFX.Client.Core.Specs.Common { public class TestBeforeValueUpdateClass : TestClassBase diff --git a/src/LogoFX.Client.Core.Specs/Common/TestMultipleClass.cs b/src/LogoFX.Client.Core.Specs/Common/TestMultipleClass.cs index 8e9ae47..b3102f3 100644 --- a/src/LogoFX.Client.Core.Specs/Common/TestMultipleClass.cs +++ b/src/LogoFX.Client.Core.Specs/Common/TestMultipleClass.cs @@ -1,3 +1,5 @@ +using LogoFX.Core; + namespace LogoFX.Client.Core.Specs.Common { public class TestMultipleClass : NotifyPropertyChangedBase diff --git a/src/LogoFX.Client.Core.Specs/Dispatcher/DispatcherSteps.cs b/src/LogoFX.Client.Core.Specs/Dispatcher/DispatcherSteps.cs index dfbe471..dea0a7d 100644 --- a/src/LogoFX.Client.Core.Specs/Dispatcher/DispatcherSteps.cs +++ b/src/LogoFX.Client.Core.Specs/Dispatcher/DispatcherSteps.cs @@ -1,25 +1,23 @@ using System.Threading; -using FluentAssertions; using LogoFX.Client.Core.Specs.Common; -using TechTalk.SpecFlow; namespace LogoFX.Client.Core.Specs.Dispatcher { [Binding] internal sealed class DispatcherSteps { - private readonly DispatcherScenarioDataStoreBase _scenarioDataStoreBase; + private readonly DispatcherScenarioDataStore _scenarioDataStore; public DispatcherSteps(ScenarioContext scenarioContext) { - _scenarioDataStoreBase = new DispatcherScenarioDataStoreBase(scenarioContext); + _scenarioDataStore = new DispatcherScenarioDataStore(scenarioContext); } [Given(@"The dispatcher is set to test dispatcher")] public void GivenTheDispatcherIsSetToTestDispatcher() { var dispatch = new FakeDispatch(); - _scenarioDataStoreBase.Dispatch = dispatch; + _scenarioDataStore.Dispatch = dispatch; Dispatch.Current = dispatch; } @@ -27,20 +25,20 @@ public void GivenTheDispatcherIsSetToTestDispatcher() public void GivenTheDispatcherIsSetToOverriddenDispatcher() { var dispatch = new OverriddenDispatch(); - _scenarioDataStoreBase.Dispatch = dispatch; + _scenarioDataStore.Dispatch = dispatch; } [Then(@"The property change notification is raised via the test dispatcher")] public void ThenThePropertyChangeNotificationIsRaisedViaTheTestDispatcher() { - var fakeDispatch = _scenarioDataStoreBase.Dispatch; + var fakeDispatch = _scenarioDataStore.Dispatch; fakeDispatch.IsOnUiThreadCalled.Should().BeTrue(); } [Then(@"The property change notification is raised via the overridden dispatcher")] public void ThenThePropertyChangeNotificationIsRaisedViaTheOverriddenDispatcher() { - var fakeDispatch = _scenarioDataStoreBase.Dispatch; + var fakeDispatch = _scenarioDataStore.Dispatch; fakeDispatch.IsOnUiThreadCalled.Should().BeTrue(); fakeDispatch.Should().BeOfType(); } diff --git a/src/LogoFX.Client.Core.Specs/ImplicitUsings.cs b/src/LogoFX.Client.Core.Specs/ImplicitUsings.cs new file mode 100644 index 0000000..7a5742e --- /dev/null +++ b/src/LogoFX.Client.Core.Specs/ImplicitUsings.cs @@ -0,0 +1,2 @@ +global using FluentAssertions; +global using TechTalk.SpecFlow; diff --git a/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs b/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs index 20c94f8..f921c1b 100644 --- a/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs +++ b/src/LogoFX.Client.Core.Specs/Notification/NotifyPropertyChangedSteps.cs @@ -3,26 +3,25 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using FluentAssertions; using LogoFX.Client.Core.Specs.Common; -using TechTalk.SpecFlow; +using LogoFX.Core.Specs.Common; namespace LogoFX.Client.Core.Specs.Notification { [Binding] internal sealed class NotifyPropertyChangedSteps { - private readonly InvocationScenarioDataStoreBase _invocationScenarioDataStoreBase; + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; public NotifyPropertyChangedSteps(ScenarioContext scenarioContext) { - _invocationScenarioDataStoreBase = new InvocationScenarioDataStoreBase(scenarioContext); + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); } [When(@"The number is changed to (.*) in silent mode")] public void WhenTheNumberIsChangedToInSilentMode(int value) { - var @class = _invocationScenarioDataStoreBase.Class as TestClassBase; + var @class = _invocationScenarioDataStore.Class as TestClassBase; @class.UpdateSilent(() => { @class.Number = value; @@ -32,7 +31,7 @@ public void WhenTheNumberIsChangedToInSilentMode(int value) [When(@"The quantity is changed to (.*) via SetProperty API")] public void WhenTheQuantityIsChangedToViaSetPropertyAPI(int value) { - var @class = _invocationScenarioDataStoreBase.Class as TestMultipleClass; + var @class = _invocationScenarioDataStore.Class as TestMultipleClass; @class.Quantity = value; } @@ -42,43 +41,35 @@ public void WhenTheIsCreatedAndAllNotificationsAreListenedTo(string name) var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name); if (@class != null) { - _invocationScenarioDataStoreBase.Class = @class; + _invocationScenarioDataStore.Class = @class; var isCallRefCollection = new List(); var isQuantityCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Quantity"); isCallRefCollection.Add(isQuantityCalledRef); var isTotalCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Total"); isCallRefCollection.Add(isTotalCalledRef); - _invocationScenarioDataStoreBase.IsCalledRefCollection = isCallRefCollection; + _invocationScenarioDataStore.IsCalledRefCollection = isCallRefCollection; } } - [Then(@"The property change notification result is '(.*)'")] - public void ThenThePropertyChangeNotificationResultIs(string expectedResultStr) - { - bool.TryParse(expectedResultStr, out var expectedResult); - var isCalledRef = _invocationScenarioDataStoreBase.IsCalledRef; - isCalledRef.Value.Should().Be(expectedResult); - } - [Then(@"The property change notification result is '(.*)' for all notifications")] public void ThenThePropertyChangeNotificationResultIsForAllNotifications(string expectedResultStr) { bool.TryParse(expectedResultStr, out var expectedResult); - var isCalledRefCollection = _invocationScenarioDataStoreBase.IsCalledRefCollection; + var isCalledRefCollection = _invocationScenarioDataStore.IsCalledRefCollection; isCalledRefCollection.Select(t => t.Value).Should().AllBeEquivalentTo(expectedResult); } [Then(@"The before value update logic is invoked before the value update")] public void ThenTheBeforeValueUpdateLogicIsInvokedBeforeTheValueUpdate() { - var @class = _invocationScenarioDataStoreBase.Class as TestBeforeValueUpdateClass; + var @class = _invocationScenarioDataStore.Class as TestBeforeValueUpdateClass; @class.PreviousValue.Should().Be(4); } [Then(@"The after value update logic is invoked after the value update")] public void ThenTheAfterValueUpdateLogicIsInvokedAfterTheValueUpdate() { - var @class = _invocationScenarioDataStoreBase.Class as TestAfterValueUpdateClass; + var @class = _invocationScenarioDataStore.Class as TestAfterValueUpdateClass; @class.Number.Should().Be(6); } } diff --git a/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreScenarioDataStoreBase.cs b/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreScenarioDataStore.cs similarity index 56% rename from src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreScenarioDataStoreBase.cs rename to src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreScenarioDataStore.cs index 8f537f4..cdff62f 100644 --- a/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreScenarioDataStoreBase.cs +++ b/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreScenarioDataStore.cs @@ -1,11 +1,10 @@ using Attest.Testing.Context.SpecFlow; -using TechTalk.SpecFlow; namespace LogoFX.Client.Core.Specs.Semaphore { - internal sealed class SemaphoreScenarioDataStoreBase : ScenarioDataStoreBase + internal sealed class SemaphoreScenarioDataStore : ScenarioDataStoreBase { - public SemaphoreScenarioDataStoreBase(ScenarioContext scenarioContext) : base(scenarioContext) + public SemaphoreScenarioDataStore(ScenarioContext scenarioContext) : base(scenarioContext) { } diff --git a/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreSteps.cs b/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreSteps.cs index 9e740e7..16c7d1d 100644 --- a/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreSteps.cs +++ b/src/LogoFX.Client.Core.Specs/Semaphore/SemaphoreSteps.cs @@ -1,50 +1,47 @@ -using FluentAssertions; -using TechTalk.SpecFlow; - -namespace LogoFX.Client.Core.Specs.Semaphore +namespace LogoFX.Client.Core.Specs.Semaphore { [Binding] internal sealed class SemaphoreSteps { - private readonly SemaphoreScenarioDataStoreBase _scenarioDataStoreBase; + private readonly SemaphoreScenarioDataStore _scenarioDataStore; public SemaphoreSteps(ScenarioContext scenarioContext) { - _scenarioDataStoreBase = new SemaphoreScenarioDataStoreBase(scenarioContext); + _scenarioDataStore = new SemaphoreScenarioDataStore(scenarioContext); } [When(@"The semaphore is created")] public void WhenTheSemaphoreIsCreated() { var semaphore = new ReentranceGuard(); - _scenarioDataStoreBase.Semaphore = semaphore; + _scenarioDataStore.Semaphore = semaphore; } [When(@"The semaphore is raised")] public void WhenTheSemaphoreIsRaised() { - var semaphore = _scenarioDataStoreBase.Semaphore; + var semaphore = _scenarioDataStore.Semaphore; semaphore.Raise(); } [When(@"The semaphore is raised and disposed")] public void WhenTheSemaphoreIsRaisedAndDisposed() { - var semaphore = _scenarioDataStoreBase.Semaphore; + var semaphore = _scenarioDataStore.Semaphore; using (semaphore.Raise()) {} } [Then(@"The semaphore should not be locked")] public void ThenTheSemaphoreShouldNotBeLocked() { - var semaphore = _scenarioDataStoreBase.Semaphore; + var semaphore = _scenarioDataStore.Semaphore; semaphore.IsLocked.Should().BeFalse(); } [Then(@"The semaphore should be locked")] public void ThenTheSemaphoreShouldBeLocked() { - var semaphore = _scenarioDataStoreBase.Semaphore; + var semaphore = _scenarioDataStore.Semaphore; semaphore.IsLocked.Should().BeTrue(); } } diff --git a/src/LogoFX.Client.Core.Specs/specflow.json b/src/LogoFX.Client.Core.Specs/specflow.json index 3c119b5..fe9927d 100644 --- a/src/LogoFX.Client.Core.Specs/specflow.json +++ b/src/LogoFX.Client.Core.Specs/specflow.json @@ -13,6 +13,9 @@ "stepAssemblies": [ { "assembly": "LogoFX.Client.Core.Specs.Common" + }, + { + "assembly": "LogoFX.Core.Specs.Common" } ] } \ No newline at end of file diff --git a/src/LogoFX.Client.Core/NotifyPropertyChangedCore.cs b/src/LogoFX.Client.Core/NotifyPropertyChangedCore.cs deleted file mode 100644 index 4b19ba3..0000000 --- a/src/LogoFX.Client.Core/NotifyPropertyChangedCore.cs +++ /dev/null @@ -1,72 +0,0 @@ -//note: I don't know who is responsible for writing out the most of this excellent stuff -//note: If you feel you are somehow involved and not mentioned in credits - let me know -using System; -using System.ComponentModel; -using System.Linq.Expressions; - -namespace LogoFX.Client.Core -{ - /// - /// Implements on behalf of a container class. - /// - /// - /// Use instead of this class if possible. - /// - /// The type of the containing class. - public sealed class NotifyPropertyChangedCore - { - /// - /// The backing delegate for . - /// - private PropertyChangedEventHandler _propertyChanged; - - /// - /// The object that contains this instance. - /// - private readonly T _obj; - - /// - /// Initializes a new instance of the class that is contained by . - /// - /// The object that contains this instance. - public NotifyPropertyChangedCore(T obj) - { - _obj = obj; - } - - /// - /// Provides notification of changes to a property value. - /// - public event PropertyChangedEventHandler PropertyChanged - { - add - { - _propertyChanged += value; - } - - remove - { - _propertyChanged -= value; - } - } - - /// - /// Raises for the given property. - /// - /// The type of the property. - /// The lambda expression identifying the property that changed. - public void OnPropertyChanged(Expression> expression) - { - _propertyChanged.Raise(_obj, expression); - } - /// - /// Raises for the given property. - /// - /// The type of the property. - /// The lambda expression identifying the property that changed. - public void OnPropertyChanged(Expression> expression) - { - _propertyChanged.Raise(_obj, expression); - } - } -} diff --git a/src/LogoFX.Core.Specs.Common/CommonSteps.cs b/src/LogoFX.Core.Specs.Common/CommonSteps.cs new file mode 100644 index 0000000..f6bcc74 --- /dev/null +++ b/src/LogoFX.Core.Specs.Common/CommonSteps.cs @@ -0,0 +1,24 @@ +using FluentAssertions; +using TechTalk.SpecFlow; + +namespace LogoFX.Core.Specs.Common +{ + [Binding] + public sealed class CommonSteps + { + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; + + public CommonSteps(ScenarioContext scenarioContext) + { + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); + } + + [Then(@"The property change notification result is '(.*)'")] + public void ThenThePropertyChangeNotificationResultIs(string expectedResultStr) + { + bool.TryParse(expectedResultStr, out var expectedResult); + var isCalledRef = _invocationScenarioDataStore.IsCalledRef; + isCalledRef.Value.Should().Be(expectedResult); + } + } +} diff --git a/src/LogoFX.Client.Core.Specs.Common/InvocationScenarioDataStoreBase.cs b/src/LogoFX.Core.Specs.Common/InvocationScenarioDataStore.cs similarity index 73% rename from src/LogoFX.Client.Core.Specs.Common/InvocationScenarioDataStoreBase.cs rename to src/LogoFX.Core.Specs.Common/InvocationScenarioDataStore.cs index 8980ed0..4d975d7 100644 --- a/src/LogoFX.Client.Core.Specs.Common/InvocationScenarioDataStoreBase.cs +++ b/src/LogoFX.Core.Specs.Common/InvocationScenarioDataStore.cs @@ -3,12 +3,12 @@ using Attest.Testing.Context.SpecFlow; using TechTalk.SpecFlow; -namespace LogoFX.Client.Core.Specs.Common +namespace LogoFX.Core.Specs.Common { [Binding] - public sealed class InvocationScenarioDataStoreBase : ScenarioDataStoreBase + public sealed class InvocationScenarioDataStore : ScenarioDataStoreBase { - public InvocationScenarioDataStoreBase(ScenarioContext scenarioContext) : base(scenarioContext) + public InvocationScenarioDataStore(ScenarioContext scenarioContext) : base(scenarioContext) { } diff --git a/src/LogoFX.Core.Specs.Common/LogoFX.Core.Specs.Common.csproj b/src/LogoFX.Core.Specs.Common/LogoFX.Core.Specs.Common.csproj new file mode 100644 index 0000000..872a55d --- /dev/null +++ b/src/LogoFX.Core.Specs.Common/LogoFX.Core.Specs.Common.csproj @@ -0,0 +1,17 @@ + + + netstandard2.0 + false + false + + + 8 + + + 8 + + + + + + \ No newline at end of file diff --git a/src/LogoFX.Core.Specs.Common/TestClassFactory.cs b/src/LogoFX.Core.Specs.Common/TestClassFactory.cs new file mode 100644 index 0000000..5d55026 --- /dev/null +++ b/src/LogoFX.Core.Specs.Common/TestClassFactory.cs @@ -0,0 +1,17 @@ +using System; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace LogoFX.Core.Specs.Common +{ + public static class TestClassFactory + { + public static INotifyPropertyChanged CreateTestClass(Assembly assembly, string name, params object?[]? args) + { + var types = assembly.DefinedTypes.ToArray(); + var type = types.FirstOrDefault(t => t.Name == name)?.AsType(); + return type == null ? null : Activator.CreateInstance(type, args) as INotifyPropertyChanged; + } + } +} diff --git a/src/LogoFX.Client.Core.Specs.Common/TestClassHelper.cs b/src/LogoFX.Core.Specs.Common/TestClassHelper.cs similarity index 54% rename from src/LogoFX.Client.Core.Specs.Common/TestClassHelper.cs rename to src/LogoFX.Core.Specs.Common/TestClassHelper.cs index b1687d0..917cee7 100644 --- a/src/LogoFX.Client.Core.Specs.Common/TestClassHelper.cs +++ b/src/LogoFX.Core.Specs.Common/TestClassHelper.cs @@ -1,11 +1,8 @@ #nullable enable -using System; using System.ComponentModel; -using System.Linq; -using System.Reflection; -namespace LogoFX.Client.Core.Specs.Common +namespace LogoFX.Core.Specs.Common { public static class TestClassHelper { @@ -22,12 +19,5 @@ public static ValueWrapper ListenToPropertyChange(INotifyPropertyChanged @class, }; return isCalledRef; } - - internal static INotifyPropertyChanged CreateTestClassImpl(Assembly assembly, string name, params object?[]? args) - { - var types = assembly.DefinedTypes.ToArray(); - var type = types.FirstOrDefault(t => t.Name == name)?.AsType(); - return type == null ? null : Activator.CreateInstance(type, args) as INotifyPropertyChanged; - } } } \ No newline at end of file diff --git a/src/LogoFX.Client.Core.Specs.Common/ValueWrapper.cs b/src/LogoFX.Core.Specs.Common/ValueWrapper.cs similarity index 79% rename from src/LogoFX.Client.Core.Specs.Common/ValueWrapper.cs rename to src/LogoFX.Core.Specs.Common/ValueWrapper.cs index 65a7aff..60d94e6 100644 --- a/src/LogoFX.Client.Core.Specs.Common/ValueWrapper.cs +++ b/src/LogoFX.Core.Specs.Common/ValueWrapper.cs @@ -1,4 +1,4 @@ -namespace LogoFX.Client.Core.Specs.Common +namespace LogoFX.Core.Specs.Common { public class ValueWrapper { diff --git a/src/LogoFX.Core.Specs/CommonSteps.cs b/src/LogoFX.Core.Specs/CommonSteps.cs new file mode 100644 index 0000000..b6d4c92 --- /dev/null +++ b/src/LogoFX.Core.Specs/CommonSteps.cs @@ -0,0 +1,28 @@ +using System.Reflection; +using LogoFX.Core.Specs.Common; + +namespace LogoFX.Core.Specs +{ + [Binding] + public sealed class CommonSteps + { + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; + + public CommonSteps(ScenarioContext scenarioContext) + { + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); + } + + [When(@"The '(.*)' is created")] + public void WhenTheIsCreated(string name) + { + var @class = TestClassFactory.CreateTestClass(Assembly.GetExecutingAssembly(), name); + if (@class != null) + { + var isCalledRef = TestClassHelper.ListenToPropertyChange(@class, "Number"); + _invocationScenarioDataStore.Class = @class; + _invocationScenarioDataStore.IsCalledRef = isCalledRef; + } + } + } +} diff --git a/src/LogoFX.Core.Specs/ImplicitUsings.cs b/src/LogoFX.Core.Specs/ImplicitUsings.cs new file mode 100644 index 0000000..c46e3f3 --- /dev/null +++ b/src/LogoFX.Core.Specs/ImplicitUsings.cs @@ -0,0 +1,2 @@ +global using FluentAssertions; +global using TechTalk.SpecFlow; \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/LogoFX.Core.Specs.csproj b/src/LogoFX.Core.Specs/LogoFX.Core.Specs.csproj new file mode 100644 index 0000000..9dd66d3 --- /dev/null +++ b/src/LogoFX.Core.Specs/LogoFX.Core.Specs.csproj @@ -0,0 +1,36 @@ + + + + net6.0 + false + enable + enable + false + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + Always + + + PreserveNewest + + + \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/Notification.feature b/src/LogoFX.Core.Specs/Notification.feature new file mode 100644 index 0000000..70ae1d0 --- /dev/null +++ b/src/LogoFX.Core.Specs/Notification.feature @@ -0,0 +1,40 @@ +Feature: Notification + In order to implement different app scenarios + As an app developer + I want the framework to handle property notifications properly + +Scenario Outline: Single property change in regular mode should raise property change notification + When The '' is created + And The number is changed to 5 in regular mode + Then The property change notification result is '' + +Examples: +| Name | Result | +| TestRegularClass | true | + +Scenario Outline: Single property change in silent mode should not raise property change notification + When The '' is created + And The number is changed to 5 in silent mode + Then The property change notification result is '' + +Examples: +| Name | Result | +| TestNameClass | false | +| TestExpressionClass | false | + +Scenario: Changing single property via SetProperty API should raise property change notification + When The 'TestRegularClass' is created + And The number is changed to 5 via SetProperty API + Then The property change notification result is 'true' + +Scenario: Changing single property with before value update logic via SetProperty API should invoke this logic before property value changes + When The 'TestBeforeValueUpdateClass' is created + And The number is changed to 5 via SetProperty API + Then The before value update logic is invoked before the value update + +Scenario: Changing single property with after value update logic via SetProperty API should invoke this logic after property value changes + When The 'TestAfterValueUpdateClass' is created + And The number is changed to 5 via SetProperty API + Then The after value update logic is invoked after the value update + + diff --git a/src/LogoFX.Core.Specs/Notification.feature.cs b/src/LogoFX.Core.Specs/Notification.feature.cs new file mode 100644 index 0000000..fc1be02 --- /dev/null +++ b/src/LogoFX.Core.Specs/Notification.feature.cs @@ -0,0 +1,326 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (https://www.specflow.org/). +// SpecFlow Version:3.9.0.0 +// SpecFlow Generator Version:3.9.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace LogoFX.Core.Specs +{ + using TechTalk.SpecFlow; + using System; + using System.Linq; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public partial class NotificationFeature : object, Xunit.IClassFixture, System.IDisposable + { + + private static TechTalk.SpecFlow.ITestRunner testRunner; + + private string[] _featureTags = ((string[])(null)); + + private Xunit.Abstractions.ITestOutputHelper _testOutputHelper; + +#line 1 "Notification.feature" +#line hidden + + public NotificationFeature(NotificationFeature.FixtureData fixtureData, LogoFX_Core_Specs_XUnitAssemblyFixture assemblyFixture, Xunit.Abstractions.ITestOutputHelper testOutputHelper) + { + this._testOutputHelper = testOutputHelper; + this.TestInitialize(); + } + + public static void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "", "Notification", "\tIn order to implement different app scenarios\r\n\tAs an app developer\r\n\tI want the" + + " framework to handle property notifications properly", ProgrammingLanguage.CSharp, ((string[])(null))); + testRunner.OnFeatureStart(featureInfo); + } + + public static void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + public virtual void TestInitialize() + { + } + + public virtual void TestTearDown() + { + testRunner.OnScenarioEnd(); + } + + public virtual void ScenarioInitialize(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioInitialize(scenarioInfo); + testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(_testOutputHelper); + } + + public virtual void ScenarioStart() + { + testRunner.OnScenarioStart(); + } + + public virtual void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + void System.IDisposable.Dispose() + { + this.TestTearDown(); + } + + [Xunit.SkippableTheoryAttribute(DisplayName="Single property change in regular mode should raise property change notification")] + [Xunit.TraitAttribute("FeatureTitle", "Notification")] + [Xunit.TraitAttribute("Description", "Single property change in regular mode should raise property change notification")] + [Xunit.InlineDataAttribute("TestRegularClass", "true", new string[0])] + public virtual void SinglePropertyChangeInRegularModeShouldRaisePropertyChangeNotification(string name, string result, string[] exampleTags) + { + string[] tagsOfScenario = exampleTags; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + argumentsOfScenario.Add("Name", name); + argumentsOfScenario.Add("Result", result); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Single property change in regular mode should raise property change notification", null, tagsOfScenario, argumentsOfScenario, this._featureTags); +#line 6 +this.ScenarioInitialize(scenarioInfo); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 7 + testRunner.When(string.Format("The \'{0}\' is created", name), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 8 + testRunner.And("The number is changed to 5 in regular mode", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 9 + testRunner.Then(string.Format("The property change notification result is \'{0}\'", result), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [Xunit.SkippableTheoryAttribute(DisplayName="Single property change in silent mode should not raise property change notificati" + + "on")] + [Xunit.TraitAttribute("FeatureTitle", "Notification")] + [Xunit.TraitAttribute("Description", "Single property change in silent mode should not raise property change notificati" + + "on")] + [Xunit.InlineDataAttribute("TestNameClass", "false", new string[0])] + [Xunit.InlineDataAttribute("TestExpressionClass", "false", new string[0])] + public virtual void SinglePropertyChangeInSilentModeShouldNotRaisePropertyChangeNotification(string name, string result, string[] exampleTags) + { + string[] tagsOfScenario = exampleTags; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + argumentsOfScenario.Add("Name", name); + argumentsOfScenario.Add("Result", result); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Single property change in silent mode should not raise property change notificati" + + "on", null, tagsOfScenario, argumentsOfScenario, this._featureTags); +#line 15 +this.ScenarioInitialize(scenarioInfo); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 16 + testRunner.When(string.Format("The \'{0}\' is created", name), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 17 + testRunner.And("The number is changed to 5 in silent mode", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 18 + testRunner.Then(string.Format("The property change notification result is \'{0}\'", result), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [Xunit.SkippableFactAttribute(DisplayName="Changing single property via SetProperty API should raise property change notific" + + "ation")] + [Xunit.TraitAttribute("FeatureTitle", "Notification")] + [Xunit.TraitAttribute("Description", "Changing single property via SetProperty API should raise property change notific" + + "ation")] + public virtual void ChangingSinglePropertyViaSetPropertyAPIShouldRaisePropertyChangeNotification() + { + string[] tagsOfScenario = ((string[])(null)); + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Changing single property via SetProperty API should raise property change notific" + + "ation", null, tagsOfScenario, argumentsOfScenario, this._featureTags); +#line 25 +this.ScenarioInitialize(scenarioInfo); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 26 + testRunner.When("The \'TestRegularClass\' is created", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 27 + testRunner.And("The number is changed to 5 via SetProperty API", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 28 + testRunner.Then("The property change notification result is \'true\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [Xunit.SkippableFactAttribute(DisplayName="Changing single property with before value update logic via SetProperty API shoul" + + "d invoke this logic before property value changes")] + [Xunit.TraitAttribute("FeatureTitle", "Notification")] + [Xunit.TraitAttribute("Description", "Changing single property with before value update logic via SetProperty API shoul" + + "d invoke this logic before property value changes")] + public virtual void ChangingSinglePropertyWithBeforeValueUpdateLogicViaSetPropertyAPIShouldInvokeThisLogicBeforePropertyValueChanges() + { + string[] tagsOfScenario = ((string[])(null)); + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Changing single property with before value update logic via SetProperty API shoul" + + "d invoke this logic before property value changes", null, tagsOfScenario, argumentsOfScenario, this._featureTags); +#line 30 +this.ScenarioInitialize(scenarioInfo); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 31 + testRunner.When("The \'TestBeforeValueUpdateClass\' is created", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 32 + testRunner.And("The number is changed to 5 via SetProperty API", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 33 + testRunner.Then("The before value update logic is invoked before the value update", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [Xunit.SkippableFactAttribute(DisplayName="Changing single property with after value update logic via SetProperty API should" + + " invoke this logic after property value changes")] + [Xunit.TraitAttribute("FeatureTitle", "Notification")] + [Xunit.TraitAttribute("Description", "Changing single property with after value update logic via SetProperty API should" + + " invoke this logic after property value changes")] + public virtual void ChangingSinglePropertyWithAfterValueUpdateLogicViaSetPropertyAPIShouldInvokeThisLogicAfterPropertyValueChanges() + { + string[] tagsOfScenario = ((string[])(null)); + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Changing single property with after value update logic via SetProperty API should" + + " invoke this logic after property value changes", null, tagsOfScenario, argumentsOfScenario, this._featureTags); +#line 35 +this.ScenarioInitialize(scenarioInfo); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 36 + testRunner.When("The \'TestAfterValueUpdateClass\' is created", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 37 + testRunner.And("The number is changed to 5 via SetProperty API", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 38 + testRunner.Then("The after value update logic is invoked after the value update", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } + this.ScenarioCleanup(); + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.9.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class FixtureData : System.IDisposable + { + + public FixtureData() + { + NotificationFeature.FeatureSetup(); + } + + void System.IDisposable.Dispose() + { + NotificationFeature.FeatureTearDown(); + } + } + } +} +#pragma warning restore +#endregion diff --git a/src/LogoFX.Core.Specs/NotifyPropertyChangedSteps.cs b/src/LogoFX.Core.Specs/NotifyPropertyChangedSteps.cs new file mode 100644 index 0000000..85694a9 --- /dev/null +++ b/src/LogoFX.Core.Specs/NotifyPropertyChangedSteps.cs @@ -0,0 +1,29 @@ +using LogoFX.Core.Specs.Common; + +namespace LogoFX.Core.Specs +{ + [Binding] + public sealed class NotifyPropertyChangedSteps + { + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; + + public NotifyPropertyChangedSteps(ScenarioContext scenarioContext) + { + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); + } + + [Then(@"The before value update logic is invoked before the value update")] + public void ThenTheBeforeValueUpdateLogicIsInvokedBeforeTheValueUpdate() + { + var @class = _invocationScenarioDataStore.Class as TestBeforeValueUpdateClass; + @class.PreviousValue.Should().Be(4); + } + + [Then(@"The after value update logic is invoked after the value update")] + public void ThenTheAfterValueUpdateLogicIsInvokedAfterTheValueUpdate() + { + var @class = _invocationScenarioDataStore.Class as TestAfterValueUpdateClass; + @class.Number.Should().Be(6); + } + } +} diff --git a/src/LogoFX.Core.Specs/NumberChangeSteps.cs b/src/LogoFX.Core.Specs/NumberChangeSteps.cs new file mode 100644 index 0000000..7744552 --- /dev/null +++ b/src/LogoFX.Core.Specs/NumberChangeSteps.cs @@ -0,0 +1,39 @@ +using LogoFX.Core.Specs.Common; + +namespace LogoFX.Core.Specs +{ + [Binding] + internal sealed class NumberChangeSteps + { + private readonly InvocationScenarioDataStore _invocationScenarioDataStore; + + public NumberChangeSteps(ScenarioContext scenarioContext) + { + _invocationScenarioDataStore = new InvocationScenarioDataStore(scenarioContext); + } + + [When(@"The number is changed to (.*) in silent mode")] + public void WhenTheNumberIsChangedToInSilentMode(int value) + { + var @class = _invocationScenarioDataStore.Class as TestClassBase; + @class.UpdateSilent(() => + { + @class.Number = value; + }); + } + + [When(@"The number is changed to (.*) in regular mode")] + public void WhenTheNumberIsChangedToInRegularMode(int value) + { + var @class = _invocationScenarioDataStore.Class as TestClassBase; + @class.Number = value; + } + + [When(@"The number is changed to (.*) via SetProperty API")] + public void WhenTheNumberIsChangedToViaSetPropertyAPI(int value) + { + var @class = _invocationScenarioDataStore.Class as TestClassBase; + @class.Number = value; + } + } +} diff --git a/src/LogoFX.Core.Specs/TestAfterValueUpdateClass.cs b/src/LogoFX.Core.Specs/TestAfterValueUpdateClass.cs new file mode 100644 index 0000000..a125a87 --- /dev/null +++ b/src/LogoFX.Core.Specs/TestAfterValueUpdateClass.cs @@ -0,0 +1,21 @@ +namespace LogoFX.Core.Specs; + +public class TestAfterValueUpdateClass : TestClassBase +{ + public TestAfterValueUpdateClass() + { + NotifyPropertyChanged = new NotifyPropertyChangedCore(this); + } + + protected override NotifyPropertyChangedCore NotifyPropertyChanged { get; } + + private int _number = 4; + public override int Number + { + get => _number; + set => NotifyPropertyChanged.SetProperty(ref _number, value, new SetPropertyOptions + { + AfterValueUpdate = () => _number = 6 + }); + } +} \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/TestBeforeValueUpdateClass.cs b/src/LogoFX.Core.Specs/TestBeforeValueUpdateClass.cs new file mode 100644 index 0000000..e69ff7c --- /dev/null +++ b/src/LogoFX.Core.Specs/TestBeforeValueUpdateClass.cs @@ -0,0 +1,24 @@ +namespace LogoFX.Core.Specs +{ + public class TestBeforeValueUpdateClass : TestClassBase + { + public TestBeforeValueUpdateClass() + { + NotifyPropertyChanged = new NotifyPropertyChangedCore(this); + } + + protected override NotifyPropertyChangedCore NotifyPropertyChanged { get; } + + private int _number = 4; + public override int Number + { + get => _number; + set => NotifyPropertyChanged.SetProperty(ref _number, value, new SetPropertyOptions() + { + BeforeValueUpdate = () => PreviousValue = _number + }); + } + + public int PreviousValue { get; private set; } + } +} \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/TestClassBase.cs b/src/LogoFX.Core.Specs/TestClassBase.cs new file mode 100644 index 0000000..2bfec18 --- /dev/null +++ b/src/LogoFX.Core.Specs/TestClassBase.cs @@ -0,0 +1,28 @@ +using System.ComponentModel; +namespace LogoFX.Core.Specs; + +public abstract class TestClassBase : INotifyPropertyChanged +{ + protected abstract INotifyPropertyChanged NotifyPropertyChanged { get; } + + public abstract int Number + { + get; + set; + } + + public event PropertyChangedEventHandler? PropertyChanged + { + add => NotifyPropertyChanged.PropertyChanged += value; + remove => NotifyPropertyChanged.PropertyChanged -= value; + } + + public void UpdateSilent(Action action) + { + using (((ISuppressNotify)NotifyPropertyChanged).SuppressNotify) + { + action(); + } + } +} + diff --git a/src/LogoFX.Core.Specs/TestExpressionClass.cs b/src/LogoFX.Core.Specs/TestExpressionClass.cs new file mode 100644 index 0000000..88b64d8 --- /dev/null +++ b/src/LogoFX.Core.Specs/TestExpressionClass.cs @@ -0,0 +1,22 @@ +namespace LogoFX.Core.Specs; + +public class TestExpressionClass : TestClassBase +{ + public TestExpressionClass() + { + NotifyPropertyChanged = new NotifyPropertyChangedCore(this); + } + + protected override NotifyPropertyChangedCore NotifyPropertyChanged { get; } + + private int _number; + public override int Number + { + get => _number; + set + { + _number = value; + NotifyPropertyChanged.OnPropertyChanged(() => Number); + } + } +} \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/TestNameClass.cs b/src/LogoFX.Core.Specs/TestNameClass.cs new file mode 100644 index 0000000..987b06a --- /dev/null +++ b/src/LogoFX.Core.Specs/TestNameClass.cs @@ -0,0 +1,22 @@ +namespace LogoFX.Core.Specs; + +public class TestNameClass : TestClassBase +{ + public TestNameClass() + { + NotifyPropertyChanged = new NotifyPropertyChangedCore(this); + } + + protected override NotifyPropertyChangedCore NotifyPropertyChanged { get; } + + private int _number; + public override int Number + { + get => _number; + set + { + _number = value; + NotifyPropertyChanged.OnPropertyChanged(); + } + } +} \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/TestRegularClass.cs b/src/LogoFX.Core.Specs/TestRegularClass.cs new file mode 100644 index 0000000..2a773eb --- /dev/null +++ b/src/LogoFX.Core.Specs/TestRegularClass.cs @@ -0,0 +1,18 @@ +namespace LogoFX.Core.Specs; +public class TestRegularClass : TestClassBase +{ + public TestRegularClass() + { + NotifyPropertyChanged = new NotifyPropertyChangedCore(this); + } + + protected override NotifyPropertyChangedCore NotifyPropertyChanged { get; } + + private int _number; + + public override int Number + { + get => _number; + set => NotifyPropertyChanged.SetProperty(ref _number, value); + } +} \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/specflow.json b/src/LogoFX.Core.Specs/specflow.json new file mode 100644 index 0000000..095924b --- /dev/null +++ b/src/LogoFX.Core.Specs/specflow.json @@ -0,0 +1,18 @@ +{ + "bindingCulture": { + "language": "en-us" + }, + "language": { + "feature": "en-us" + }, + "livingDocGenerator": { + "enabled": true, + "filePath": "TestExecution.json" + }, + "plugins":[], + "stepAssemblies": [ + { + "assembly": "LogoFX.Core.Specs.Common" + } + ] +} \ No newline at end of file diff --git a/src/LogoFX.Core.Specs/xunit.runner.json b/src/LogoFX.Core.Specs/xunit.runner.json new file mode 100644 index 0000000..9db029b --- /dev/null +++ b/src/LogoFX.Core.Specs/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "parallelizeAssembly": false, + "parallelizeTestCollections": false +} diff --git a/src/LogoFX.Core.sln b/src/LogoFX.Core.sln index 4cea4b3..b27b447 100644 --- a/src/LogoFX.Core.sln +++ b/src/LogoFX.Core.sln @@ -49,7 +49,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogoFX.Client.Theming.Platf EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogoFX.Client.Theming.Platform.WPF", "LogoFX.Client.Theming.Platform\netframework\LogoFX.Client.Theming.Platform.WPF.csproj", "{3720D35C-1548-4B53-A37D-31A5C7D49A20}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogoFX.Client.Core.Specs.Common", "LogoFX.Client.Core.Specs.Common\LogoFX.Client.Core.Specs.Common.csproj", "{728663E9-62A0-4482-8F0A-832699835760}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogoFX.Client.Core.Specs.Common", "LogoFX.Client.Core.Specs.Common\LogoFX.Client.Core.Specs.Common.csproj", "{728663E9-62A0-4482-8F0A-832699835760}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogoFX.Core.Specs", "LogoFX.Core.Specs\LogoFX.Core.Specs.csproj", "{DF5B56B9-783A-457F-B8E1-EEA9EE033E91}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogoFX.Core.Specs.Common", "LogoFX.Core.Specs.Common\LogoFX.Core.Specs.Common.csproj", "{C2C89A94-96B9-43DA-841C-3F78ED059DDF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -383,6 +387,38 @@ Global {728663E9-62A0-4482-8F0A-832699835760}.Release|x64.Build.0 = Release|Any CPU {728663E9-62A0-4482-8F0A-832699835760}.Release|x86.ActiveCfg = Release|Any CPU {728663E9-62A0-4482-8F0A-832699835760}.Release|x86.Build.0 = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|ARM.Build.0 = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|x64.Build.0 = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Debug|x86.Build.0 = Debug|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|Any CPU.Build.0 = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|ARM.ActiveCfg = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|ARM.Build.0 = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|x64.ActiveCfg = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|x64.Build.0 = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|x86.ActiveCfg = Release|Any CPU + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91}.Release|x86.Build.0 = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|ARM.Build.0 = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|x64.Build.0 = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Debug|x86.Build.0 = Debug|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|Any CPU.Build.0 = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|ARM.ActiveCfg = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|ARM.Build.0 = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|x64.ActiveCfg = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|x64.Build.0 = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|x86.ActiveCfg = Release|Any CPU + {C2C89A94-96B9-43DA-841C-3F78ED059DDF}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -408,6 +444,8 @@ Global {C802E723-0E2D-49AC-81CE-D435C8303F48} = {61BF3ACA-38BF-4273-B93A-732FB0D08CED} {3720D35C-1548-4B53-A37D-31A5C7D49A20} = {61BF3ACA-38BF-4273-B93A-732FB0D08CED} {728663E9-62A0-4482-8F0A-832699835760} = {F555D153-CB40-4452-B5E4-E9731566272E} + {DF5B56B9-783A-457F-B8E1-EEA9EE033E91} = {F555D153-CB40-4452-B5E4-E9731566272E} + {C2C89A94-96B9-43DA-841C-3F78ED059DDF} = {F555D153-CB40-4452-B5E4-E9731566272E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AC15861E-3935-4FBC-AA56-C0C4CFF71FC3} diff --git a/src/LogoFX.Core/NotifyPropertyChangedCore.cs b/src/LogoFX.Core/NotifyPropertyChangedCore.cs new file mode 100644 index 0000000..de4f11d --- /dev/null +++ b/src/LogoFX.Core/NotifyPropertyChangedCore.cs @@ -0,0 +1,147 @@ +//note: I don't know who is responsible for writing out the most of this excellent stuff +//note: If you feel you are somehow involved and not mentioned in credits - let me know +using System; +using System.ComponentModel; +using System.Linq.Expressions; +using System.Runtime.CompilerServices; + +namespace LogoFX.Core +{ + /// + /// Implements on behalf of a container class. + /// + /// The type of the containing class. + public sealed class NotifyPropertyChangedCore : INotifyPropertyChanged, ISuppressNotify + { + /// + /// The backing delegate for . + /// + private PropertyChangedEventHandler _propertyChanged; + + /// + /// The object that contains this instance. + /// + private readonly T _obj; + + /// + /// Initializes a new instance of the class that is contained by . + /// + /// The object that contains this instance. + public NotifyPropertyChangedCore(T obj) + { + _obj = obj; + } + + /// + /// Provides notification of changes to a property value. + /// + public event PropertyChangedEventHandler PropertyChanged + { + add + { + _propertyChanged += value; + } + + remove + { + _propertyChanged -= value; + } + } + + /// + /// Raises for the given property. + /// + /// The type of the property. + /// The lambda expression identifying the property that changed. + public void OnPropertyChanged(Expression> expression) + { + InvokeAction(() => _propertyChanged.Raise(_obj, expression)); + } + /// + /// Raises for the given property. + /// + /// The type of the property. + /// The lambda expression identifying the property that changed. + public void OnPropertyChanged(Expression> expression) + { + InvokeAction(() => _propertyChanged.Raise(_obj, expression)); + } + + public void OnPropertyChanged([CallerMemberName] string name = "") + { + InvokeAction(() => _propertyChanged.Raise(this, name)); + } + + /// + /// Compares the current and new values. If they are different, + /// updates the respective field + /// and fires the property change notification. + /// + /// The type of the property. + /// The current value field reference. + /// The new value. + /// The property name. + /// The set property options. + public void SetProperty( + ref TProperty currentValue, + TProperty newValue, + SetPropertyOptions options = null, + [CallerMemberName] string name = "") + { + //Can't use delegate here because of ref parameter + if (!_notifyManager.IsMuted) + { + SetPropertyImpl(ref currentValue, newValue, options, name); + } + } + + private void SetPropertyImpl(ref TProperty currentValue, TProperty newValue, SetPropertyOptions options, + string name) + { + if (Equals(currentValue, newValue)) + { + return; + } + + if (options?.CustomActionInvocation != null) + { + options.CustomActionInvocation(() => { options?.BeforeValueUpdate?.Invoke(); }); + currentValue = newValue; + options.CustomActionInvocation(() => + { + if (!_notifyManager.IsMuted) + { + _propertyChanged.Raise(this, name); + } + + options?.AfterValueUpdate?.Invoke(); + }); + } + else + { + options?.BeforeValueUpdate?.Invoke(); + currentValue = newValue; + OnPropertyChanged(name); + options?.AfterValueUpdate?.Invoke(); + } + } + + private readonly INotifyManager _notifyManager = new NotifyManager(); + + IDisposable ISuppressNotify.SuppressNotify => SuppressNotify; + + /// + /// Gets the suppress notify. + /// To be used in using statement. + /// + public IDisposable SuppressNotify => new SuppressNotifyHelper(_notifyManager); + + private void InvokeAction(Action action) + { + if (!_notifyManager.IsMuted) + { + action(); + } + } + } +} diff --git a/src/LogoFX.Client.Core/PropertyChangedEventHandlerExtensions.cs b/src/LogoFX.Core/PropertyChangedEventHandlerExtensions.cs similarity index 99% rename from src/LogoFX.Client.Core/PropertyChangedEventHandlerExtensions.cs rename to src/LogoFX.Core/PropertyChangedEventHandlerExtensions.cs index c1d11e6..c83d006 100644 --- a/src/LogoFX.Client.Core/PropertyChangedEventHandlerExtensions.cs +++ b/src/LogoFX.Core/PropertyChangedEventHandlerExtensions.cs @@ -1,11 +1,12 @@ //note: I don't know who is responsible for writing out the most of this excellent stuff //note: If you feel you are somehow involved and not mentioned in credits - let me know + using System; using System.ComponentModel; using System.Linq.Expressions; using System.Reflection; -namespace LogoFX.Client.Core +namespace LogoFX.Core { /// /// Provides extension methods for delegates. diff --git a/src/LogoFX.Client.Core/PropertyChangedExtensions.cs b/src/LogoFX.Core/PropertyChangedExtensions.cs similarity index 99% rename from src/LogoFX.Client.Core/PropertyChangedExtensions.cs rename to src/LogoFX.Core/PropertyChangedExtensions.cs index 43da526..9e0cd8c 100644 --- a/src/LogoFX.Client.Core/PropertyChangedExtensions.cs +++ b/src/LogoFX.Core/PropertyChangedExtensions.cs @@ -1,11 +1,12 @@ //note: I don't know who is responsible for writing out the most of this excellent stuff //note: If you feel you are somehow involved and not mentioned in credits - let me know + using System; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; -namespace LogoFX.Client.Core +namespace LogoFX.Core { /// /// - ideas from http://michaelsync.net/2009/04/09/silverlightwpf-implementing-propertychanged-with-expression-tree diff --git a/src/LogoFX.Client.Core/SetPropertyOptions.cs b/src/LogoFX.Core/SetPropertyOptions.cs similarity index 96% rename from src/LogoFX.Client.Core/SetPropertyOptions.cs rename to src/LogoFX.Core/SetPropertyOptions.cs index a8f70ae..9080007 100644 --- a/src/LogoFX.Client.Core/SetPropertyOptions.cs +++ b/src/LogoFX.Core/SetPropertyOptions.cs @@ -1,8 +1,9 @@ //note: I don't know who is responsible for writing out the most of this excellent stuff //note: If you feel you are somehow involved and not mentioned in credits - let me know + using System; -namespace LogoFX.Client.Core +namespace LogoFX.Core { /// /// Set property options. Use this to inject functionality on property value update. diff --git a/src/LogoFX.Practices.IoC.Specs/ContainerScenarioDataStoreBase.cs b/src/LogoFX.Practices.IoC.Specs/ContainerScenarioDataStore.cs similarity index 82% rename from src/LogoFX.Practices.IoC.Specs/ContainerScenarioDataStoreBase.cs rename to src/LogoFX.Practices.IoC.Specs/ContainerScenarioDataStore.cs index cb31264..c71ed1f 100644 --- a/src/LogoFX.Practices.IoC.Specs/ContainerScenarioDataStoreBase.cs +++ b/src/LogoFX.Practices.IoC.Specs/ContainerScenarioDataStore.cs @@ -3,9 +3,9 @@ namespace LogoFX.Practices.IoC.Specs { - internal sealed class ContainerScenarioDataStoreBase : ScenarioDataStoreBase + internal sealed class ContainerScenarioDataStore : ScenarioDataStoreBase { - public ContainerScenarioDataStoreBase(ScenarioContext scenarioContext) : base(scenarioContext) + public ContainerScenarioDataStore(ScenarioContext scenarioContext) : base(scenarioContext) { } diff --git a/src/LogoFX.Practices.IoC.Specs/ExtendedSimpleContainerSteps.cs b/src/LogoFX.Practices.IoC.Specs/ExtendedSimpleContainerSteps.cs index 714dae2..8a31edc 100644 --- a/src/LogoFX.Practices.IoC.Specs/ExtendedSimpleContainerSteps.cs +++ b/src/LogoFX.Practices.IoC.Specs/ExtendedSimpleContainerSteps.cs @@ -8,24 +8,24 @@ namespace LogoFX.Practices.IoC.Specs [Binding] internal sealed class ExtendedSimpleContainerSteps { - private readonly ContainerScenarioDataStoreBase _scenarioDataStoreBase; + private readonly ContainerScenarioDataStore _scenarioDataStore; public ExtendedSimpleContainerSteps(ScenarioContext scenarioContext) { - _scenarioDataStoreBase = new ContainerScenarioDataStoreBase(scenarioContext); + _scenarioDataStore = new ContainerScenarioDataStore(scenarioContext); } [When(@"The container is created")] public void WhenTheContainerIsCreated() { var container = new ExtendedSimpleContainer(); - _scenarioDataStoreBase.Container = container; + _scenarioDataStore.Container = container; } [When(@"The dependency with named parameter is registered in transient fashion")] public void WhenTheDependencyWithNamedParameterIsRegisteredInTransientFashion() { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; container.RegisterPerRequest(typeof(ITestNamedParameterDependency), null, typeof(TestNamedParameterDependency)); } @@ -33,7 +33,7 @@ public void WhenTheDependencyWithNamedParameterIsRegisteredInTransientFashion() [When(@"The dependency with typed parameter is registered in transient fashion")] public void WhenTheDependencyWithTypedParameterIsRegisteredInTransientFashion() { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; container.RegisterPerRequest(typeof(ITestTypedParameterDependency), null, typeof(TestTypedParameterDependency)); } @@ -41,7 +41,7 @@ public void WhenTheDependencyWithTypedParameterIsRegisteredInTransientFashion() [When(@"The dependency with named parameter is registered in singleton fashion")] public void WhenTheDependencyWithNamedParameterIsRegisteredInSingletonFashion() { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; container.RegisterSingleton((c, r) => new TestModule {Name = "1"}); } @@ -57,45 +57,45 @@ public void WhenTheSameTypeDependencyIsRegisteredInInstanceFashionUsingSecondIns RegisterInstanceDependency((r, v) => r.SecondModule = v, new TestModule { Name = "2" }); } - private void RegisterInstanceDependency(Action valueSetter, ITestModule instance) + private void RegisterInstanceDependency(Action valueSetter, ITestModule instance) { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; var module = new TestModule { Name = "1" }; container.RegisterHandler(typeof(ITestModule), null, (c, r) => instance); - valueSetter(_scenarioDataStoreBase, instance); + valueSetter(_scenarioDataStore, instance); } [When(@"The dependency is resolved with value '(.*)' for named parameter")] public void WhenTheDependencyIsResolvedWithValueForNamedParameter(string parameter) { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; var dependency = container.GetInstance(typeof(ITestNamedParameterDependency), null, new IParameter[] { new NamedParameter("model", parameter) }) as ITestNamedParameterDependency; - _scenarioDataStoreBase.Dependency = dependency; + _scenarioDataStore.Dependency = dependency; } [When(@"The dependency is resolved with value (.*) for typed parameter")] public void WhenTheDependencyIsResolvedWithValueForTypedParameter(int parameter) { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; const int val = 6; var dependency = container.GetInstance(typeof(ITestTypedParameterDependency), null, new IParameter[] { new TypedParameter(typeof(int), val) }) as ITestTypedParameterDependency; - _scenarioDataStoreBase.Dependency = dependency; + _scenarioDataStore.Dependency = dependency; } [When(@"The collection of dependencies is resolved")] public void WhenTheCollectionOfDependenciesIsResolved() { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; var dependencies = container.GetAllInstances(typeof(ITestModule)).ToArray(); - _scenarioDataStoreBase.Dependencies = dependencies; + _scenarioDataStore.Dependencies = dependencies; } [Then(@"Actual value of parameter inside the named dependency is '(.*)'")] public void ThenActualValueOfParameterInsideTheNamedDependencyIs(string parameter) { - var dependency = _scenarioDataStoreBase.Dependency as ITestNamedParameterDependency; + var dependency = _scenarioDataStore.Dependency as ITestNamedParameterDependency; var actualModel = dependency.Model; actualModel.Should().Be(parameter); } @@ -103,7 +103,7 @@ public void ThenActualValueOfParameterInsideTheNamedDependencyIs(string paramete [Then(@"Actual value of parameter inside the typed dependency is (.*)")] public void ThenActualValueOfParameterInsideTheTypedDependencyIs(int parameter) { - var dependency = _scenarioDataStoreBase.Dependency as ITestTypedParameterDependency; + var dependency = _scenarioDataStore.Dependency as ITestTypedParameterDependency; var actualValue = dependency.Value; actualValue.Should().Be(parameter); } @@ -111,9 +111,9 @@ public void ThenActualValueOfParameterInsideTheTypedDependencyIs(int parameter) [Then(@"The collection of dependencies is equivalent to the collection of instances")] public void ThenTheCollectionOfDependenciesIsEquivalentToTheCollectionOfInstances() { - var dependencies = _scenarioDataStoreBase.Dependencies.OfType().ToArray(); + var dependencies = _scenarioDataStore.Dependencies.OfType().ToArray(); var modules = new[] - {_scenarioDataStoreBase.FirstModule, _scenarioDataStoreBase.SecondModule}; + {_scenarioDataStore.FirstModule, _scenarioDataStore.SecondModule}; dependencies.Should().BeSubsetOf(modules); modules.Should().BeSubsetOf(dependencies); } @@ -121,7 +121,7 @@ public void ThenTheCollectionOfDependenciesIsEquivalentToTheCollectionOfInstance [Then(@"Multiple dependency resolutions yield same value")] public void ThenMultipleDependencyResolutionsYieldSameValue() { - var container = _scenarioDataStoreBase.Container; + var container = _scenarioDataStore.Container; var module = container.GetInstance(typeof(ITestModule), null); var actualModule = container.GetInstance(typeof(ITestModule), null);