diff --git a/Build.ps1 b/Build.ps1 index 247ea052e..7bef21b9b 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -55,7 +55,7 @@ task Compile -precondition {return $compile } { InvokeScript{ write-host "Building Tests" -f "Blue" dotnet restore "$PSScriptRoot\src\Tests\Tests.sln" --source $source - dotnet msbuild "$PSScriptRoot\src\Tests\Tests.sln" "/p:OutDir=$PSScriptRoot\bin" + dotnet msbuild "$PSScriptRoot\src\Tests\Tests.sln" #"/p:OutDir=$PSScriptRoot\bin" } } diff --git a/src/Tests/CloneModelView/CloneModelViewTests.cs b/src/Tests/CloneModelView/CloneModelViewTests.cs index be899380c..d038b6d56 100644 --- a/src/Tests/CloneModelView/CloneModelViewTests.cs +++ b/src/Tests/CloneModelView/CloneModelViewTests.cs @@ -1,8 +1,6 @@ using System; using System.Linq; -using System.Reactive.Concurrency; using System.Reactive.Linq; -using System.Threading.Tasks; using DevExpress.ExpressApp.DC; using DevExpress.ExpressApp.Model; using Fasterflect; @@ -15,36 +13,10 @@ using Xunit; namespace Xpand.XAF.Modules.CloneModelView.Tests{ - public static class MyRxExtensions{ - - - public static IObservable RetryWithBackoff(this IObservable source,int retryCount = 3, - Func strategy = null,Func retryOnError = null,IScheduler scheduler = null){ - strategy = strategy ?? (n =>TimeSpan.FromSeconds(Math.Pow(n, 2))) ; - var attempt = 0; - retryOnError = retryOnError ?? (_ => true); - return Observable.Defer(() => (++attempt == 1 ? source : source.DelaySubscription(strategy(attempt - 1), scheduler)) - .Select(item => (true, item, (Exception)null)) - .Catch<(bool, T, Exception), Exception>(e =>retryOnError(e)? Observable.Throw<(bool, T, Exception)>(e) - : Observable.Return<(bool, T, Exception)>((false, default, e)))) - .Retry(retryCount) - .SelectMany(t => t.Item1 - ? Observable.Return(t.Item2) - : Observable.Throw(t.Item3)); - } - - public static IObservable DelaySubscription(this IObservable source, - TimeSpan delay, IScheduler scheduler = null){ - if (scheduler == null) return Observable.Timer(delay).SelectMany(_ => source); - return Observable.Timer(delay, scheduler).SelectMany(_ => source); - } - } [Collection(nameof(CloneModelViewModule))] public class CloneModelViewTests : BaseTest{ - protected async Task Execute(Action action){ - await Observable.Defer(() => Observable.Start(action)).RetryWithBackoff(3,retryOnError:exception => true).FirstAsync(); - } + [Theory] [InlineData(CloneViewType.LookupListView, Platform.Win)] @@ -53,49 +25,45 @@ public class CloneModelViewTests : BaseTest{ [InlineData(CloneViewType.LookupListView,Platform.Web)] [InlineData(CloneViewType.ListView,Platform.Web)] [InlineData(CloneViewType.DetailView,Platform.Web)] - internal async Task Clone_Model_View(CloneViewType cloneViewType, Platform platform){ + internal void Clone_Model_View(CloneViewType cloneViewType, Platform platform){ - await Execute(() => { - var cloneViewId = $"{nameof(Clone_Model_View)}{platform}_{cloneViewType}"; - - var application = DefaultCloneModelViewModule(info => { - var cloneModelViewAttribute = new CloneModelViewAttribute(cloneViewType, cloneViewId); - info.FindTypeInfo(typeof(CMV)).AddAttribute(cloneModelViewAttribute); - }, platform).Application; - var modelView = application.Model.Views[cloneViewId]; - modelView.ShouldNotBeNull(); - modelView.GetType().Name.ShouldBe($"Model{cloneViewType.ToString().Replace("Lookup", "")}"); - modelView.Id.ShouldBe(cloneViewId); - application.Dispose(); - }); + var cloneViewId = $"{nameof(Clone_Model_View)}{platform}_{cloneViewType}"; + var application = DefaultCloneModelViewModule(info => { + var cloneModelViewAttribute = new CloneModelViewAttribute(cloneViewType, cloneViewId); + info.FindTypeInfo(typeof(CMV)).AddAttribute(cloneModelViewAttribute); + }, platform).Application; + ((bool) application.GetPropertyValue("EnableModelCache")).ShouldBe(false); + + var modelView = application.Model.Views[cloneViewId]; + modelView.ShouldNotBeNull(); + modelView.GetType().Name.ShouldBe($"Model{cloneViewType.ToString().Replace("Lookup", "")}"); + modelView.Id.ShouldBe(cloneViewId); + application.Dispose(); } [Theory] [InlineData(Platform.Web)] [InlineData(Platform.Win)] - internal async Task Clone_multiple_Model_Views(Platform platform){ - await Execute(() => { - var cloneViewId = $"{nameof(Clone_multiple_Model_Views)}{platform}_"; - var cloneViewTypes = Enum.GetValues(typeof(CloneViewType)).Cast(); - var application = DefaultCloneModelViewModule(info => { - foreach (var cloneViewType in cloneViewTypes){ - var cloneModelViewAttribute = - new CloneModelViewAttribute(cloneViewType, $"{cloneViewId}{cloneViewType}"); - info.FindTypeInfo(typeof(CMV)).AddAttribute(cloneModelViewAttribute); - } - }, platform).Application; + internal void Clone_multiple_Model_Views(Platform platform){ + var cloneViewId = $"{nameof(Clone_multiple_Model_Views)}{platform}_"; + var cloneViewTypes = Enum.GetValues(typeof(CloneViewType)).Cast(); + var application = DefaultCloneModelViewModule(info => { foreach (var cloneViewType in cloneViewTypes){ - var viewId = $"{cloneViewId}{cloneViewType}"; - var modelView = application.Model.Views[viewId]; - modelView.ShouldNotBeNull(); - modelView.GetType().Name.ShouldBe($"Model{cloneViewType.ToString().Replace("Lookup", "")}"); - modelView.Id.ShouldBe(viewId); + var cloneModelViewAttribute = + new CloneModelViewAttribute(cloneViewType, $"{cloneViewId}{cloneViewType}"); + info.FindTypeInfo(typeof(CMV)).AddAttribute(cloneModelViewAttribute); } + }, platform).Application; + foreach (var cloneViewType in cloneViewTypes){ + var viewId = $"{cloneViewId}{cloneViewType}"; + var modelView = application.Model.Views[viewId]; + modelView.ShouldNotBeNull(); + modelView.GetType().Name.ShouldBe($"Model{cloneViewType.ToString().Replace("Lookup", "")}"); + modelView.Id.ShouldBe(viewId); + } - application.Dispose(); - }); - } + application.Dispose(); } [Theory] [InlineData(CloneViewType.LookupListView, Platform.Win)] @@ -104,57 +72,47 @@ public class CloneModelViewTests : BaseTest{ [InlineData(CloneViewType.LookupListView,Platform.Web)] [InlineData(CloneViewType.ListView,Platform.Web)] [InlineData(CloneViewType.DetailView,Platform.Web)] - internal async Task Clone_Model_View_and_make_it_default(CloneViewType cloneViewType, Platform platform){ - await Execute(() => { - var cloneViewId = $"{nameof(Clone_Model_View_and_make_it_default)}_{cloneViewType}{platform}"; + internal void Clone_Model_View_and_make_it_default(CloneViewType cloneViewType, Platform platform){ + var cloneViewId = $"{nameof(Clone_Model_View_and_make_it_default)}_{cloneViewType}{platform}"; - var application = DefaultCloneModelViewModule(info => { - var cloneModelViewAttribute = new CloneModelViewAttribute(cloneViewType, cloneViewId, true); - info.FindTypeInfo(typeof(CMV)).AddAttribute(cloneModelViewAttribute); - }, platform).Application; - var modelView = application.Model.Views[cloneViewId].AsObjectView; + var application = DefaultCloneModelViewModule(info => { + var cloneModelViewAttribute = new CloneModelViewAttribute(cloneViewType, cloneViewId, true); + info.FindTypeInfo(typeof(CMV)).AddAttribute(cloneModelViewAttribute); + }, platform).Application; + var modelView = application.Model.Views[cloneViewId].AsObjectView; - ((IModelView) modelView.ModelClass.GetPropertyValue($"Default{cloneViewType}")).Id - .ShouldBe(cloneViewId); - application.Dispose(); - }); - } + ((IModelView) modelView.ModelClass.GetPropertyValue($"Default{cloneViewType}")).Id + .ShouldBe(cloneViewId); + application.Dispose(); } [Theory] [InlineData(CloneViewType.LookupListView, Platform.Win)] [InlineData(CloneViewType.ListView, Platform.Win)] [InlineData(CloneViewType.LookupListView,Platform.Web)] [InlineData(CloneViewType.ListView,Platform.Web)] - internal async Task Clone_Model_ListView_and_change_its_detailview(CloneViewType cloneViewType, Platform platform){ - await Execute(() => { - var cloneViewId = $"{nameof(Clone_Model_ListView_and_change_its_detailview)}{platform}_"; - var listViewId = $"{cloneViewId}{cloneViewType}"; - var detailViewId = $"{cloneViewType}DetailView"; - var application = DefaultCloneModelViewModule(info => { - var typeInfo = info.FindTypeInfo(typeof(CMV)); - typeInfo.AddAttribute(new CloneModelViewAttribute(CloneViewType.DetailView, detailViewId)); - typeInfo.AddAttribute(new CloneModelViewAttribute(cloneViewType, listViewId) - {DetailView = detailViewId}); - }, platform).Application; - var modelListView = (IModelListView) application.Model.Views[listViewId]; - modelListView.DetailView.Id.ShouldBe(detailViewId); - application.Dispose(); - }); - } + internal void Clone_Model_ListView_and_change_its_detailview(CloneViewType cloneViewType, Platform platform){ + var cloneViewId = $"{nameof(Clone_Model_ListView_and_change_its_detailview)}{platform}_"; + var listViewId = $"{cloneViewId}{cloneViewType}"; + var detailViewId = $"{cloneViewType}DetailView"; + var application = DefaultCloneModelViewModule(info => { + var typeInfo = info.FindTypeInfo(typeof(CMV)); + typeInfo.AddAttribute(new CloneModelViewAttribute(CloneViewType.DetailView, detailViewId)); + typeInfo.AddAttribute(new CloneModelViewAttribute(cloneViewType, listViewId) + {DetailView = detailViewId}); + }, platform).Application; + var modelListView = (IModelListView) application.Model.Views[listViewId]; + modelListView.DetailView.Id.ShouldBe(detailViewId); + application.Dispose(); } - private static CloneModelViewModule DefaultCloneModelViewModule(Action customizeTypesInfo, - Platform platform){ + private static CloneModelViewModule DefaultCloneModelViewModule(Action customizeTypesInfo,Platform platform){ var application = platform.NewApplication(); application.WhenCustomizingTypesInfo().FirstAsync(info => { customizeTypesInfo(info); return true; }) .Subscribe(); - var cloneModelViewModule = new CloneModelViewModule(); - cloneModelViewModule.AdditionalExportedTypes.AddRange(new[]{typeof(CMV)}); - cloneModelViewModule.RequiredModuleTypes.Add(typeof(ReactiveModule)); - application.SetupDefaults(cloneModelViewModule); - return cloneModelViewModule; + application.Modules.Add(new ReactiveModule()); + return application.AddModule(typeof(CMV)); } } } \ No newline at end of file diff --git a/src/Tests/ModelViewInheritance/ModelViewInheritanceTests.cs b/src/Tests/ModelViewInheritance/ModelViewInheritanceTests.cs index ea219f43e..394941c46 100644 --- a/src/Tests/ModelViewInheritance/ModelViewInheritanceTests.cs +++ b/src/Tests/ModelViewInheritance/ModelViewInheritanceTests.cs @@ -15,23 +15,25 @@ public class ModelViewInheritanceTests:BaseTest { [Theory] [ClassData(typeof(ModelViewInheritanceTestData))] internal void Inherit_And_Modify_A_BaseView(ViewType viewType, bool attribute,Platform platform){ - ModelViewInheritanceUpdater.Disabled = true; - var models = GetModels(viewType, attribute, platform); - var application = platform.NewApplication(); - var modelViewIneritanceModule = CreateModelViewIneritanceModule(viewType, attribute, application); - var testModule1 = new TestModule1{DiffsStore = new StringModelStore(models[0])}; - var baseBoTypes = new[]{typeof(ABaseMvi), typeof(TagMvi)}; - var boTypes = new[]{typeof(AMvi), typeof(FileMvi)}; - testModule1.AdditionalExportedTypes.AddRange(baseBoTypes); - var testModule2 = new TestModule2{DiffsStore = new StringModelStore(models[1])}; - testModule2.AdditionalExportedTypes.AddRange(boTypes); + for (int i = 0; i < 30; i++){ + ModelViewInheritanceUpdater.Disabled = true; + var models = GetModels(viewType, attribute, platform); + var application = platform.NewApplication(); + var modelViewIneritanceModule = CreateModelViewIneritanceModule(viewType, attribute, application); + var testModule1 = new TestModule1{DiffsStore = new StringModelStore(models[0])}; + var baseBoTypes = new[]{typeof(ABaseMvi), typeof(TagMvi)}; + var boTypes = new[]{typeof(AMvi), typeof(FileMvi)}; + testModule1.AdditionalExportedTypes.AddRange(baseBoTypes); + var testModule2 = new TestModule2{DiffsStore = new StringModelStore(models[1])}; + testModule2.AdditionalExportedTypes.AddRange(boTypes); - application.SetupDefaults(modelViewIneritanceModule, testModule1, testModule2, - new TestModule3{DiffsStore = new StringModelStore(models[2])}); - var inheritAndModifyBaseView = new InheritAndModifyBaseView(application, viewType, attribute); + application.SetupDefaults(modelViewIneritanceModule, testModule1, testModule2, + new TestModule3{DiffsStore = new StringModelStore(models[2])}); + var inheritAndModifyBaseView = new InheritAndModifyBaseView(application, viewType, attribute); - inheritAndModifyBaseView.Verify(application.Model); - application.Dispose(); + inheritAndModifyBaseView.Verify(application.Model); + application.Dispose(); + } } private static string[] GetModels(ViewType viewType, bool attribute, Platform platform){ @@ -60,10 +62,11 @@ public class ModelViewInheritanceTests:BaseTest { private static void CustomizeTypesInfo(ViewType viewType, bool attribute, XafApplication application){ if (attribute){ application.WhenCustomizingTypesInfo() - .Do(_ => { + .FirstAsync(_=> { _.FindTypeInfo(typeof(AMvi)) .AddAttribute(new ModelMergedDifferencesAttribute($"{nameof(AMvi)}_{viewType}", $"{nameof(ABaseMvi)}_{viewType}")); + return true; }) .Subscribe(); } diff --git a/src/Tests/TestsLib/BaseTest.cs b/src/Tests/TestsLib/BaseTest.cs index f16ccbeaa..a5d67efa2 100644 --- a/src/Tests/TestsLib/BaseTest.cs +++ b/src/Tests/TestsLib/BaseTest.cs @@ -1,10 +1,43 @@ -using DevExpress.ExpressApp; +using System; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using DevExpress.ExpressApp; using DevExpress.ExpressApp.Xpo; using Xunit.Abstractions; using IDisposable = System.IDisposable; namespace TestsLib{ + public static class MyRxExtensions{ + + + public static IObservable RetryWithBackoff(this IObservable source,int retryCount = 3, + Func strategy = null,Func retryOnError = null,IScheduler scheduler = null){ + strategy = strategy ?? (n =>TimeSpan.FromSeconds(Math.Pow(n, 2))) ; + var attempt = 0; + retryOnError = retryOnError ?? (_ => true); + return Observable.Defer(() => (++attempt == 1 ? source : source.DelaySubscription(strategy(attempt - 1), scheduler)) + .Select(item => (true, item, (Exception)null)) + .Catch<(bool, T, Exception), Exception>(e =>retryOnError(e)? Observable.Throw<(bool, T, Exception)>(e) + : Observable.Return<(bool, T, Exception)>((false, default, e)))) + .Retry(retryCount) + .SelectMany(t => t.Item1 + ? Observable.Return(t.Item2) + : Observable.Throw(t.Item3)); + } + + public static IObservable DelaySubscription(this IObservable source, + TimeSpan delay, IScheduler scheduler = null){ + if (scheduler == null) return Observable.Timer(delay).SelectMany(_ => source); + return Observable.Timer(delay, scheduler).SelectMany(_ => source); + } + } + public abstract class BaseTest : IDisposable{ + + protected async Task Execute(Action action){ + await Observable.Defer(() => Observable.Start(action)).RetryWithBackoff(3,retryOnError:exception => true).FirstAsync(); + } public const string NotImplemented = "NotImplemented"; protected BaseTest(ITestOutputHelper output){ Output = output; diff --git a/tools/Build/lab-Pipeline.yml b/tools/Build/lab-Pipeline.yml index a891a6d77..27c137cd6 100644 --- a/tools/Build/lab-Pipeline.yml +++ b/tools/Build/lab-Pipeline.yml @@ -30,44 +30,44 @@ steps: targetType: filePath filePath: .\tools\build\lab-pipeline.ps1 arguments: $(Build.SourceBranchName) $(System.DefaultworkingDirectory) $(GitHubUserName) $(GitHubPass) $(DXApiFeed) $(build.artifactstagingdirectory) $(AzureToken) -- task: PublishBuildArtifacts@1 - inputs: - PathtoPublish: '.\bin' - ArtifactName: 'drop' - publishLocation: 'Container' -# - task: VSTest@2 -# displayName: 'VsTest - testAssemblies' -# inputs: -# searchFolder: '$(System.DefaultWorkingDirectory)' -# testSelector: 'testAssemblies' -# testAssemblyVer2: | -# **\*Tests*.dll -# !**\*TestAdapter.dll -# !**\obj\** -# runInParallel: false -# diagnosticsEnabled: true -# runTestsInIsolation: false -# codeCoverageEnabled: true -# rerunFailedTests: true -# rerunMaxAttempts: 3 -# collectDumpOn: never -# - task: PowerShell@2 -# displayName: CheckTests -# inputs: -# pwsh: true -# targetType: filePath -# filePath: .\tools\build\check-tests.ps1 -# arguments: $(AzureToken) $(Build.DefinitionName) $(Build.BuildNumber) -# - powershell: | -# - task: PowerShell@2 -# displayName: Publish -# inputs: -# pwsh: true -# targetType: filePath -# filePath: .\tools\build\publishNugets.ps1 -# arguments: $(Build.SourceBranchName) $(System.DefaultworkingDirectory) $(NugetApiKey) # - task: PublishBuildArtifacts@1 -# displayName: 'Publish Artifact: Packages' # inputs: -# PathtoPublish: '$(build.artifactstagingdirectory)' -# ArtifactName: 'Xpand.XAF.Modules.Packages' +# PathtoPublish: '.\bin' +# ArtifactName: 'drop' +# publishLocation: 'Container' +- task: VSTest@2 + displayName: 'VsTest - testAssemblies' + inputs: + searchFolder: '$(System.DefaultWorkingDirectory)' + testSelector: 'testAssemblies' + testAssemblyVer2: | + **\*Tests*.dll + !**\*TestAdapter.dll + !**\obj\** + runInParallel: false + diagnosticsEnabled: true + runTestsInIsolation: true + codeCoverageEnabled: true + rerunFailedTests: true + rerunMaxAttempts: 3 + collectDumpOn: never +- task: PowerShell@2 + displayName: CheckTests + inputs: + pwsh: true + targetType: filePath + filePath: .\tools\build\check-tests.ps1 + arguments: $(AzureToken) $(Build.DefinitionName) $(Build.BuildNumber) +- powershell: | +- task: PowerShell@2 + displayName: Publish + inputs: + pwsh: true + targetType: filePath + filePath: .\tools\build\publishNugets.ps1 + arguments: $(Build.SourceBranchName) $(System.DefaultworkingDirectory) $(NugetApiKey) +- task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: Packages' + inputs: + PathtoPublish: '$(build.artifactstagingdirectory)' + ArtifactName: 'Xpand.XAF.Modules.Packages'