diff options
Diffstat (limited to 'main/src/addins/MonoDevelop.PackageManagement')
12 files changed, 1496 insertions, 21 deletions
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs index 7a8f8b95f5..f2626ffde6 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs @@ -56,7 +56,7 @@ namespace MonoDevelop.PackageManagement AddPackagesDialog CreateDialog (string initialSearch)
{
- var viewModel = new AllPackagesViewModel (recentPackagesRepository);
+ var viewModel = AllPackagesViewModel.Create (recentPackagesRepository);
return new AddPackagesDialog (
viewModel,
initialSearch);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs new file mode 100644 index 0000000000..ad25422976 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetProject.cs @@ -0,0 +1,74 @@ +// +// FakeNuGetProject.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.Frameworks; +using NuGet.Packaging; +using NuGet.Packaging.Core; +using NuGet.ProjectManagement; +using NuGet.Protocol.Core.Types; +using NuGet.Versioning; + +namespace MonoDevelop.PackageManagement.Tests.Helpers +{ + class FakeNuGetProject : NuGetProject + { + public FakeNuGetProject (IDotNetProject project) + { + Project = project; + } + + public IDotNetProject Project { get; private set; } + + public List<PackageReference> InstalledPackages = new List<PackageReference> (); + + public override Task<IEnumerable<PackageReference>> GetInstalledPackagesAsync (CancellationToken token) + { + return Task.FromResult (InstalledPackages.AsEnumerable ()); + } + + public override Task<bool> InstallPackageAsync (PackageIdentity packageIdentity, DownloadResourceResult downloadResourceResult, INuGetProjectContext nuGetProjectContext, CancellationToken token) + { + throw new NotImplementedException (); + } + + public override Task<bool> UninstallPackageAsync (PackageIdentity packageIdentity, INuGetProjectContext nuGetProjectContext, CancellationToken token) + { + throw new NotImplementedException (); + } + + public void AddPackageReference (string id, string version) + { + var packageId = new PackageIdentity (id, new NuGetVersion (version)); + InstalledPackages.Add (new PackageReference (packageId, new NuGetFramework ("net45"))); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetSettings.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetSettings.cs new file mode 100644 index 0000000000..5704d28232 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeNuGetSettings.cs @@ -0,0 +1,101 @@ +// +// FakeNuGetSettings.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using NuGet.Configuration; + +namespace MonoDevelop.PackageManagement.Tests.Helpers +{ + class FakeNuGetSettings : ISettings + { + public string FileName { + get { + throw new NotImplementedException (); + } + } + + public IEnumerable<ISettings> Priority { + get { + throw new NotImplementedException (); + } + } + + public string Root { + get { + throw new NotImplementedException (); + } + } + + public event EventHandler SettingsChanged; + + public bool DeleteSection (string section) + { + throw new NotImplementedException (); + } + + public bool DeleteValue (string section, string key) + { + throw new NotImplementedException (); + } + + public IList<KeyValuePair<string, string>> GetNestedValues (string section, string subSection) + { + throw new NotImplementedException (); + } + + public IList<SettingValue> GetSettingValues (string section, bool isPath = false) + { + throw new NotImplementedException (); + } + + public string GetValue (string section, string key, bool isPath = false) + { + return null; + } + + public void SetNestedValues (string section, string subSection, IList<KeyValuePair<string, string>> values) + { + throw new NotImplementedException (); + } + + public void SetValue (string section, string key, string value) + { + throw new NotImplementedException (); + } + + public void SetValues (string section, IReadOnlyList<SettingValue> values) + { + throw new NotImplementedException (); + } + + public void UpdateSections (string section, IReadOnlyList<SettingValue> values) + { + throw new NotImplementedException (); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageSourceProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageSourceProvider.cs index e7c65edd91..c676994474 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageSourceProvider.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageSourceProvider.cs @@ -35,8 +35,8 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers {
public List<PackageSource> PackageSources = new List<PackageSource> ();
public List<PackageSource> SavedPackageSources;
- public PackageSource ActivatePackageSource;
-
+ public PackageSource ActivePackageSource; + public string ActivePackageSourceName { get; set; }
public event EventHandler PackageSourcesChanged;
@@ -62,7 +62,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public void SaveActivePackageSource (PackageSource source)
{
- ActivatePackageSource = source;
+ ActivePackageSource = source;
ActivePackageSourceName = source?.Name;
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs new file mode 100644 index 0000000000..8691c441d8 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolutionManager.cs @@ -0,0 +1,144 @@ +// +// FakeSolutionManager.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using NuGet.Configuration; +using NuGet.PackageManagement; +using NuGet.ProjectManagement; +using NuGet.Protocol.Core.Types; + +namespace MonoDevelop.PackageManagement.Tests.Helpers +{ + class FakeSolutionManager : IMonoDevelopSolutionManager + { + public FakeSolutionManager () + { + SolutionDirectory = @"d:\projects\MyProject".ToNativePath (); + } + + public NuGetProject DefaultNuGetProject { + get { + throw new NotImplementedException (); + } + } + + public string DefaultNuGetProjectName { + get { + throw new NotImplementedException (); + } + + set { + throw new NotImplementedException (); + } + } + + public bool IsSolutionAvailable { + get { + throw new NotImplementedException (); + } + } + + public bool IsSolutionOpen { + get { + throw new NotImplementedException (); + } + } + + public INuGetProjectContext NuGetProjectContext { + get { + throw new NotImplementedException (); + } + + set { + throw new NotImplementedException (); + } + } + + public FakeNuGetSettings FakeSettings = new FakeNuGetSettings (); + + public ISettings Settings { + get { return FakeSettings; } + } + + public string SolutionDirectory { get; set; } + + #pragma warning disable 67 + public event EventHandler<ActionsExecutedEventArgs> ActionsExecuted; + public event EventHandler<NuGetProjectEventArgs> NuGetProjectAdded; + public event EventHandler<NuGetProjectEventArgs> NuGetProjectRemoved; + public event EventHandler<NuGetProjectEventArgs> NuGetProjectRenamed; + public event EventHandler SolutionClosed; + public event EventHandler SolutionClosing; + public event EventHandler SolutionOpened; + public event EventHandler SolutionOpening; + #pragma warning restore 67 + + public FakeSourceRepositoryProvider SourceRepositoryProvider = new FakeSourceRepositoryProvider (); + + public ISourceRepositoryProvider CreateSourceRepositoryProvider () + { + return SourceRepositoryProvider; + } + + public NuGetProject GetNuGetProject (string nuGetProjectSafeName) + { + throw new NotImplementedException (); + } + + public Dictionary<IDotNetProject, FakeNuGetProject> NuGetProjects = new Dictionary<IDotNetProject, FakeNuGetProject> (); + + public NuGetProject GetNuGetProject (IDotNetProject project) + { + FakeNuGetProject nugetProject = null; + if (NuGetProjects.TryGetValue (project, out nugetProject)) + return nugetProject; + + return new FakeNuGetProject (project); + } + + public IEnumerable<NuGetProject> GetNuGetProjects () + { + throw new NotImplementedException (); + } + + public string GetNuGetProjectSafeName (NuGetProject nuGetProject) + { + throw new NotImplementedException (); + } + + public void OnActionsExecuted (IEnumerable<ResolvedAction> actions) + { + throw new NotImplementedException (); + } + + public void ReloadSettings () + { + throw new NotImplementedException (); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSourceRepositoryProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSourceRepositoryProvider.cs new file mode 100644 index 0000000000..9a8e485526 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSourceRepositoryProvider.cs @@ -0,0 +1,65 @@ +// +// FakeSourceRepositoryProvider.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using NuGet.Configuration; +using NuGet.Protocol.Core.Types; + +namespace MonoDevelop.PackageManagement.Tests.Helpers +{ + class FakeSourceRepositoryProvider : ISourceRepositoryProvider + { + public List<SourceRepository> Repositories = new List<SourceRepository> (); + public FakePackageSourceProvider FakePackageSourceProvider = new FakePackageSourceProvider (); + + public IPackageSourceProvider PackageSourceProvider { + get { return FakePackageSourceProvider; } + } + + public SourceRepository CreateRepository (PackageSource source) + { + return new SourceRepository (source, new INuGetResourceProvider[0]); + } + + public IEnumerable<SourceRepository> GetRepositories () + { + return Repositories; + } + + public void AddRepositories (IEnumerable<PackageSource> sources) + { + foreach (PackageSource source in sources) { + AddRepository (source); + } + } + + public void AddRepository (PackageSource source) + { + Repositories.Add (CreateRepository (source)); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs new file mode 100644 index 0000000000..9d2586dcbb --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs @@ -0,0 +1,102 @@ +// +// TestableAllPackagesViewModel.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using NuGet.PackageManagement.UI; +using NuGet.Protocol.Core.Types; + +namespace MonoDevelop.PackageManagement.Tests.Helpers +{ + class TestableAllPackagesViewModel : AllPackagesViewModel + { + public RecentNuGetPackagesRepository RecentPackagesRepository; + public FakeNuGetProjectContext FakeNuGetProjectContext; + + public TestableAllPackagesViewModel ( + IMonoDevelopSolutionManager solutionManager, + IDotNetProject dotNetProject) + : this ( + solutionManager, + dotNetProject, + new FakeNuGetProjectContext (), + new RecentNuGetPackagesRepository ()) + { + } + + public TestableAllPackagesViewModel ( + IMonoDevelopSolutionManager solutionManager, + IDotNetProject dotNetProject, + FakeNuGetProjectContext projectContext, + RecentNuGetPackagesRepository recentPackagesRepository) + : base (solutionManager, dotNetProject, projectContext, recentPackagesRepository) + { + FakeNuGetProjectContext = projectContext; + RecentPackagesRepository = recentPackagesRepository; + } + + public FakePackageFeed PackageFeed = new FakePackageFeed (); + + protected override IPackageFeed CreatePackageFeed (IEnumerable<SourceRepository> sourceRepositories) + { + return PackageFeed; + } + + protected override Task CreateReadPackagesTask () + { + ReadPackagesTask = base.CreateReadPackagesTask (); + return ReadPackagesTask; + } + + public Task ReadPackagesTask; + + protected override Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token) + { + if (LoadPackagesAsyncTask != null) { + return LoadPackagesAsyncTask (loader, token); + } + return base.LoadPackagesAsync (loader, token); + } + + public Func<PackageItemLoader, CancellationToken, Task> LoadPackagesAsyncTask; + + public Task CallBaseLoadPackagesAsyncTask (PackageItemLoader loader, CancellationToken token) + { + return base.LoadPackagesAsync (loader, token); + } + + public Task GetPackagesInstalledInProjectTask; + + protected override Task GetPackagesInstalledInProject () + { + GetPackagesInstalledInProjectTask = base.GetPackagesInstalledInProject (); + return GetPackagesInstalledInProjectTask; + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj index 6539afc086..d1c30d4a54 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj @@ -246,6 +246,13 @@ <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProjectAction.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProjectContext.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\NuGetPackageUninstallerTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\AllPackagesViewModelTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSolutionManager.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProject.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSourceRepositoryProvider.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetSettings.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\FakePackageFeed.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableAllPackagesViewModel.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs new file mode 100644 index 0000000000..67b65888ad --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs @@ -0,0 +1,862 @@ +// +// AllPackagesViewModelTests.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using MonoDevelop.PackageManagement.Tests.Helpers; +using NuGet.Configuration; +using NuGet.PackageManagement.UI; +using NuGet.ProjectManagement; +using NuGet.Versioning; +using NUnit.Framework; + +namespace MonoDevelop.PackageManagement.Tests +{ + [TestFixture] + public class AllPackagesViewModelTests + { + TestableAllPackagesViewModel viewModel; + FakeSolutionManager solutionManager; + FakeDotNetProject project; + FakePackageSourceProvider packageSourceProvider; + + void CreateProject () + { + project = new FakeDotNetProject (); + solutionManager = new FakeSolutionManager (); + packageSourceProvider = solutionManager.SourceRepositoryProvider.FakePackageSourceProvider; + } + + void CreateViewModel () + { + viewModel = new TestableAllPackagesViewModel ( + solutionManager, + project); + EnsurePackageSourcesLoaded (); + } + + void EnsurePackageSourcesLoaded () + { + viewModel.PackageSources.ToList (); + } + + PackageSource[] AddTwoPackageSourcesToRegisteredSources () + { + var sources = new [] { + new PackageSource ("http://first.com", "First"), + new PackageSource ("http://second.com", "Second") + }; + solutionManager.SourceRepositoryProvider.AddRepositories (sources); + + return sources; + } + + PackageSource AddOnePackageSourceToRegisteredSources () + { + var source = new PackageSource ("http://monodevelop.com", "Test"); + solutionManager.SourceRepositoryProvider.AddRepository (source); + return source; + } + + Task SetUpTwoPackageSourcesAndViewModelHasReadPackages () + { + CreateProject (); + var sources = AddTwoPackageSourcesToRegisteredSources ().ToList (); + packageSourceProvider.ActivePackageSourceName = sources[0].Name; + CreateViewModel (); + EnsurePackageSourcesLoaded (); + viewModel.ReadPackages (); + return viewModel.ReadPackagesTask; + } + + void ChangeSelectedPackageSourceToFirstSourceNonAggregateSource () + { + var firstPackageSource = viewModel.PackageSources.First (source => !source.IsAggregate); + viewModel.SelectedPackageSource = firstPackageSource; + } + + void ChangeSelectedPackageSourceToSecondNonAggregateSource () + { + var secondPackageSource = viewModel + .PackageSources + .Where (source => !source.IsAggregate) + .Skip (1) + .First (); + viewModel.SelectedPackageSource = secondPackageSource; + } + + void AddRecentPackage (string packageId, string packageVersion, string packageSource) + { + var recentPackage = new PackageItemListViewModel { + Id = packageId, + Version = new NuGetVersion (packageVersion) + }; + var searchResultViewModel = new PackageSearchResultViewModel (null, recentPackage); + viewModel.RecentPackagesRepository.AddPackage (searchResultViewModel, packageSource); + } + + FakeNuGetProject CreateNuGetProjectForProject () + { + var nugetProject = new FakeNuGetProject (project); + solutionManager.NuGetProjects[project] = nugetProject; + return nugetProject; + } + + [Test] + public void PackageSources_TwoPackageSourcesInOptions_ReturnsTwoPackageSourcesPlusAggregatePackageSource () + { + CreateProject (); + var expectedPackageSources = AddTwoPackageSourcesToRegisteredSources ().ToList (); + CreateViewModel (); + expectedPackageSources.Insert (0, AggregateSourceRepositoryViewModel.AggregatePackageSource); + + var packageSources = viewModel.PackageSources.Select (vm => vm.PackageSource).ToList (); + + PackageSourceCollectionAssert.AreEqual (expectedPackageSources, packageSources); + } + + [Test] + public void PackageSources_OnePackageSourceInOptions_ReturnsOnePackageSource () + { + CreateProject (); + var packageSource = AddOnePackageSourceToRegisteredSources (); + var expectedPackageSources = new [] { packageSource }; + CreateViewModel (); + + var packageSources = viewModel.PackageSources.Select (vm => vm.PackageSource).ToList (); + + PackageSourceCollectionAssert.AreEqual (expectedPackageSources, packageSources); + } + + [Test] + public async Task ReadPackages_RepositoryHasOnePackage_PackageLoaded () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("Test", "0.1"); + + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + var package = viewModel.PackageViewModels.Single (); + Assert.AreEqual ("Test", package.Id); + Assert.AreEqual ("0.1", package.Version.ToString ()); + } + + [Test] + public void SelectedPackageSource_TwoPackageSourcesInOptionsAndActivePackageSourceIsFirstSource_IsFirstPackageSource () + { + CreateProject (); + var sources = AddTwoPackageSourcesToRegisteredSources ().ToList (); + var expectedPackageSource = sources[0]; + packageSourceProvider.ActivePackageSourceName = expectedPackageSource.Name; + CreateViewModel (); + + Assert.AreEqual (expectedPackageSource, viewModel.SelectedPackageSource.PackageSource); + } + + [Test] + public void SelectedPackageSource_TwoPackageSourcesInOptionsAndActivePackageSourceIsSecondSource_IsSecondPackageSource () + { + CreateProject (); + var sources = AddTwoPackageSourcesToRegisteredSources (); + var expectedPackageSource = sources[1]; + packageSourceProvider.ActivePackageSourceName = expectedPackageSource.Name; + CreateViewModel (); + + Assert.AreEqual (expectedPackageSource, viewModel.SelectedPackageSource.PackageSource); + } + + [Test] + public void SelectedPackageSource_OnePackageSourceDefinedButUnknownActivePackageSource_PackageSourceIsMadeActiveSource () + { + CreateProject (); + var sources = AddTwoPackageSourcesToRegisteredSources (); + var expectedPackageSource = sources[0]; + packageSourceProvider.ActivePackageSourceName = "Unknown"; + CreateViewModel (); + + Assert.AreEqual (expectedPackageSource, viewModel.SelectedPackageSource.PackageSource); + } + + [Test] + public void SelectedPackageSource_Changed_ActivePackageSourceChanged () + { + CreateProject (); + var packageSources = AddTwoPackageSourcesToRegisteredSources ().ToList (); + packageSourceProvider.ActivePackageSourceName = packageSources[0].Name; + CreateViewModel (); + var expectedPackageSource = packageSources[1]; + var packageSourceViewModels = viewModel.PackageSources.ToList (); + + viewModel.SelectedPackageSource = packageSourceViewModels[2]; + + Assert.AreEqual (expectedPackageSource, packageSourceProvider.ActivePackageSource); + } + + [Test] + public async Task SelectedPackageSource_PackageSourceChangedAfterReadingPackages_PackagesReadFromNewPackageSourceAndDisplayed () + { + await SetUpTwoPackageSourcesAndViewModelHasReadPackages (); + viewModel.ReadPackagesTask = null; + viewModel.PackageFeed.AddPackage ("Test", "1.2"); + ChangeSelectedPackageSourceToSecondNonAggregateSource (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (1, viewModel.PackageViewModels.Count); + Assert.AreEqual ("Test", viewModel.PackageViewModels[0].Id); + Assert.AreSame ("1.2", viewModel.PackageViewModels[0].Version.ToString ()); + } + + [Test] + public async Task SelectedPackageSource_PackageSourceChangedAfterReadingPackages_PropertyChangedEventFiredAfterPackagesAreRead () + { + await SetUpTwoPackageSourcesAndViewModelHasReadPackages (); + + int packageCountWhenPropertyChangedEventFired = -1; + viewModel.PropertyChanged += (sender, e) => { + packageCountWhenPropertyChangedEventFired = viewModel.PackageViewModels.Count; + }; + viewModel.ReadPackagesTask = null; + viewModel.PackageFeed.AddPackage ("Test", "1.0"); + ChangeSelectedPackageSourceToSecondNonAggregateSource (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (1, packageCountWhenPropertyChangedEventFired); + } + + [Test] + public async Task SelectedPackageSource_PackageSourceChangedButToSameSelectedPackageSource_PackagesAreNotRead () + { + await SetUpTwoPackageSourcesAndViewModelHasReadPackages (); + viewModel.ReadPackagesTask = null; + ChangeSelectedPackageSourceToFirstSourceNonAggregateSource (); + + Assert.IsNull (viewModel.ReadPackagesTask); + } + + [Test] + public async Task SelectedPackageSource_PackageSourceChangedButToSameSelectedPackageSource_PropertyChangedEventNotFired () + { + await SetUpTwoPackageSourcesAndViewModelHasReadPackages (); + + bool fired = false; + viewModel.PropertyChanged += (sender, e) => fired = true; + ChangeSelectedPackageSourceToFirstSourceNonAggregateSource (); + + Assert.IsFalse (fired); + } + + [Test] + public async Task ReadPackages_SearchTextAndIncludePrereleaseIsTrue_SearchTextAndIncludePrereleaseUsedWhenQueryingPackageFeed () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.IncludePrerelease = true; + viewModel.SearchTerms = "Test"; + viewModel.PackageFeed.AddPackage ("Test", "1.1.0-alpha"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual ("Test", viewModel.PackageFeed.SearchText); + Assert.IsTrue (viewModel.PackageFeed.SearchFilter.IncludePrerelease); + } + + [Test] + public async Task ReadPackages_NoSearchTextAndIncludePrereleaseIsFalse_SearchTextAndIncludePrereleaseIsFalseWhenQueryingPackageFeed () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.IncludePrerelease = false; + viewModel.SearchTerms = null; + viewModel.PackageFeed.AddPackage ("Test", "1.1"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (string.Empty, viewModel.PackageFeed.SearchText); + Assert.IsFalse (viewModel.PackageFeed.SearchFilter.IncludePrerelease); + } + + [Test] + public async Task ReadPackages_ExceptionThrownDuringLoad_ExceptionIsShownAsErrorMessage () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.LoadPackagesAsyncTask = (loader, token) => { + return Task.Run (() => { + throw new Exception ("Invalid url"); + }); + }; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.IsTrue (viewModel.HasError); + Assert.AreEqual ("Invalid url", viewModel.ErrorMessage); + } + + [Test] + public async Task ReadPackages_OneRecentPackageIsAvailable_RecentPackageIsDisplayedBeforeAnyOtherPackages () + { + CreateProject (); + var packageSource = AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + AddRecentPackage ("Recent", "2.1", packageSource.Name); + viewModel.PackageFeed.AddPackage ("Test", "1.3"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (2, viewModel.PackageViewModels.Count); + Assert.AreEqual ("Recent", viewModel.PackageViewModels[0].Id); + Assert.AreEqual ("Test", viewModel.PackageViewModels[1].Id); + } + + [Test] + public async Task ReadPackages_OneRecentPackageIsAvailableWhichMatchesPackageFromActiveSource_DuplicatePackageWithSameVersionFromActivePackageSourceIsNotDisplayed () + { + CreateProject (); + var packageSource = AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + AddRecentPackage ("A", "2.1", packageSource.Name); + viewModel.PackageFeed.AddPackage ("A", "2.5"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (1, viewModel.PackageViewModels.Count); + Assert.IsTrue (viewModel.PackageViewModels[0].IsRecentPackage); + Assert.AreEqual ("A", viewModel.PackageViewModels[0].Id); + } + + [Test] + public async Task ReadPackages_OneRecentPackageIsAvailableAndSearchTermEntered_RecentPackageIsNotDisplayed () + { + CreateProject (); + var packageSource = AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + AddRecentPackage ("A", "2.1", packageSource.Name); + viewModel.SearchTerms = "A"; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (0, viewModel.PackageViewModels.Count); + } + + [Test] + public async Task HasNextPage_TwoPagesOfData_HasNextPageIsFalseAfterSecondRead () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("Test", "1.3"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + bool hasNextPageAfterFirstRead = viewModel.HasNextPage; + viewModel.ReadPackagesTask = null; + viewModel.ShowNextPage (); + await viewModel.ReadPackagesTask; + + Assert.IsTrue (hasNextPageAfterFirstRead); + Assert.IsFalse (viewModel.HasNextPage); + } + + [Test] + public void IsReadingPackages_ReadPackagesNotCalled_ReturnsFalse () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + + Assert.IsFalse (viewModel.IsReadingPackages); + } + + [Test] + public async Task IsReadingPackages_ReadPackagesCalled_ReturnsTrue () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + bool readingPackages = false; + viewModel.LoadPackagesAsyncTask = (loader, token) => { + readingPackages = viewModel.IsReadingPackages; + return Task.FromResult (0); + }; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.IsTrue (readingPackages); + } + + [Test] + public async Task ErrorMessage_BackgroundTaskHasAggregateExceptionWithNestedInnerAggregateException_ErrorMessageTakenFromInnerException () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.LoadPackagesAsyncTask = (loader, token) => { + return Task.Run (() => { + var innerEx1 = new Exception ("Test1"); + var innerEx2 = new Exception ("Test2"); + var innerAggregateEx = new AggregateException (innerEx1, innerEx2); + var aggregateEx = new AggregateException (innerAggregateEx); + throw aggregateEx; + }); + }; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + string expectedErrorMessage = + "Test1" + Environment.NewLine + + "Test2"; + + Assert.AreEqual (expectedErrorMessage, viewModel.ErrorMessage); + } + + [Test] + public async Task HasError_ErrorMessageDisplayedAndSelectedPageChangedAfterFailure_ReturnsFalse () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.LoadPackagesAsyncTask = (loader, token) => { + return Task.Run (() => { + throw new Exception ("Error"); + }); + }; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + bool firstError = viewModel.HasError; + viewModel.ReadPackagesTask = null; + viewModel.LoadPackagesAsyncTask = null; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.IsFalse (viewModel.HasError); + Assert.AreEqual (string.Empty, viewModel.ErrorMessage); + Assert.IsTrue (firstError); + } + + [Test] + public void IsDisposed_DisposeMethodCalled_ReturnsTrue () + { + CreateProject (); + CreateViewModel (); + viewModel.Dispose (); + + Assert.IsTrue (viewModel.IsDisposed); + } + + [Test] + public void IsDisposed_DisposeMethodNotCalled_ReturnsFalse () + { + CreateProject (); + CreateViewModel (); + + Assert.IsFalse (viewModel.IsDisposed); + } + + [Test] + public async Task IncludePrerelease_ChangedToTrue_PackagesAreReadAgain () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.IncludePrerelease = false; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.ReadPackagesTask = null; + + viewModel.IncludePrerelease = true; + + Assert.IsNotNull (viewModel.ReadPackagesTask); + } + + [Test] + public async Task IncludePrerelease_ChangedToFalse_PackagesAreReadAgain () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.IncludePrerelease = true; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.ReadPackagesTask = null; + + viewModel.IncludePrerelease = false; + + Assert.IsNotNull (viewModel.ReadPackagesTask); + } + + [Test] + public async Task IncludePrerelease_ChangedToTrue_PropertyChangedEventIsFired () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.IncludePrerelease = false; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.ReadPackagesTask = null; + PropertyChangedEventArgs propertyChangedEvent = null; + viewModel.PropertyChanged += (sender, e) => propertyChangedEvent = e; + + viewModel.IncludePrerelease = true; + + Assert.IsNull (propertyChangedEvent.PropertyName); + } + + [Test] + public async Task IncludePrerelease_SetToTrueWhenAlreadyTrue_PropertyChangedEventIsNotFired () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.IncludePrerelease = true; + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.ReadPackagesTask = null; + bool fired = false; + viewModel.PropertyChanged += (sender, e) => fired = true; + + viewModel.IncludePrerelease = true; + + Assert.IsFalse (fired); + } + + [Test] + public async Task CheckedPackageViewModels_TwoPackagesAndOnePackageIsChecked_ReturnsOneCheckedPackage () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("A", "1.2"); + viewModel.PackageFeed.AddPackage ("B", "1.3"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + viewModel.PackageViewModels[0].IsChecked = true; + + Assert.AreEqual (2, viewModel.PackageViewModels.Count); + Assert.AreEqual (1, viewModel.CheckedPackageViewModels.Count); + Assert.AreEqual ("A", viewModel.CheckedPackageViewModels[0].Id); + } + + [Test] + public async Task CheckedPackageViewModels_OnePackageIsCheckedThenNewSearchReturnsNoPackages_ReturnsCheckedPackageEvenWhenNotVisible () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.PackageViewModels[0].IsChecked = true; + viewModel.PackageFeed = new FakePackageFeed (); + viewModel.PackageFeed.AddPackage ("AnotherPackage", "1.2"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + Assert.AreEqual (1, viewModel.CheckedPackageViewModels.Count); + Assert.AreEqual ("MyPackage", viewModel.CheckedPackageViewModels[0].Id); + } + + [Test] + public async Task CheckedPackageViewModels_OnePackageIsCheckedAndThenUnchecked_ReturnsNoCheckedPackages () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.2"); + viewModel.PackageFeed.AddPackage ("Z-Package", "1.3"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + var packageViewModel = viewModel.PackageViewModels[0]; + packageViewModel.IsChecked = true; + packageViewModel.IsChecked = false; + + Assert.AreEqual (0, viewModel.CheckedPackageViewModels.Count); + } + + [Test] + public async Task PackageViewModels_OnePackageIsCheckedAndNewSearchReturnsOriginalPackage_PackageViewHasIsCheckedSetToTrue () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.PackageViewModels[0].IsChecked = true; + viewModel.PackageFeed = new FakePackageFeed (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.Search (); + await viewModel.ReadPackagesTask; + + var packageViewModel = viewModel.PackageViewModels[0]; + + Assert.AreEqual ("MyPackage", packageViewModel.Id); + Assert.IsTrue (packageViewModel.IsChecked); + } + + [Test] + public async Task PackageViewModels_OnePackageIsCheckedAndNewSearchReturnsOriginalPackageButWithDifferentVersion_PackageViewIsCheckedAndSameVersionIsSelectedAsTheFirstPackageChecked () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.PackageViewModels[0].IsChecked = true; + viewModel.PackageFeed = new FakePackageFeed (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.1"); + viewModel.Search (); + await viewModel.ReadPackagesTask; + + var packageViewModel = viewModel.PackageViewModels[0]; + + Assert.AreEqual ("MyPackage", packageViewModel.Id); + Assert.IsTrue (packageViewModel.IsChecked); + Assert.AreEqual ("1.0", packageViewModel.SelectedVersion.ToString ()); + Assert.AreEqual (2, packageViewModel.Versions.Count); + Assert.AreEqual ("1.1", packageViewModel.Versions[0].ToString ()); + Assert.AreEqual ("1.0", packageViewModel.Versions[1].ToString ()); + } + + [Test] + public async Task CheckedPackageViewModels_OnePackageIsCheckedAndNewSearchReturnsMultipleVersionsOfOriginalPackage_OnlyPackageWithSameVersionIsChecked () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.PackageViewModels[0].IsChecked = true; + viewModel.PackageFeed = new FakePackageFeed (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.1"); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.2"); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.3"); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.4"); + viewModel.Search (); + await viewModel.ReadPackagesTask; + + var packageViewModel = viewModel.CheckedPackageViewModels.FirstOrDefault (); + + Assert.AreEqual ("MyPackage", packageViewModel.Id); + Assert.AreEqual ("1.4", packageViewModel.Version.ToString ()); + Assert.AreEqual ("1.0", packageViewModel.SelectedVersion.ToString ()); + Assert.AreEqual (1, viewModel.CheckedPackageViewModels.Count); + } + + [Test] + public async Task PackageViewModels_OnePackageIsCheckedAndNewSearchReturnsOriginalPackageWhichIsThenUncheckedByUser_NoCheckedPackageViewModels () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.PackageViewModels [0].IsChecked = true; + viewModel.PackageFeed = new FakePackageFeed (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.Search (); + await viewModel.ReadPackagesTask; + var packageViewModel = viewModel.PackageViewModels[0]; + + viewModel.PackageViewModels[0].IsChecked = false; + + Assert.AreEqual (0, viewModel.CheckedPackageViewModels.Count); + } + + [Test] + public async Task CheckedPackageViewModels_OnePackageVersionIsCheckedThenDifferentVersionChecked_OldVersionIsUnchecked () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.1"); // Old + viewModel.PackageFeed.AddPackage ("MyPackage", "1.2"); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.0"); + viewModel.PackageFeed.AddPackage ("MyPackage", "1.3"); // New + viewModel.PackageFeed.AddPackage ("MyPackage", "1.4"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + var oldPackageVersionViewModel = viewModel + .PackageViewModels + .First (item => item.Version.ToString () == "1.1"); + var newPackageVersionViewModel = viewModel + .PackageViewModels + .First (item => item.Version.ToString () == "1.3"); + oldPackageVersionViewModel.IsChecked = true; + + newPackageVersionViewModel.IsChecked = true; + + Assert.AreEqual (1, viewModel.CheckedPackageViewModels.Count); + Assert.AreEqual ("MyPackage", viewModel.CheckedPackageViewModels[0].Id); + Assert.AreEqual ("1.3", viewModel.CheckedPackageViewModels[0].Version.ToString ()); + Assert.IsFalse (oldPackageVersionViewModel.IsChecked); + } + + [Test] + public async Task Log_ErrorReportedForOnePackageSource_ErrorDisplayed () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + bool propertyChangedEventFired = false; + viewModel.PropertyChanged += (sender, e) => propertyChangedEventFired = true; + var logger = viewModel as INuGetUILogger; + logger.Log (MessageLevel.Error, "Error"); + + Assert.IsTrue (viewModel.HasError); + Assert.AreEqual ("Error", viewModel.ErrorMessage); + Assert.IsTrue (propertyChangedEventFired); + } + + [Test] + public async Task Log_TwoPackageSourcesOneReportsErrorWhenAggregateSourceSelected_OnePackageSourceCouldNotBeReachedErrorDisplayed () + { + CreateProject (); + AddTwoPackageSourcesToRegisteredSources (); + CreateViewModel (); + viewModel.SelectedPackageSource = viewModel.PackageSources.First (); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + var logger = viewModel as INuGetUILogger; + logger.Log (MessageLevel.Error, "Test error occurred"); + + Assert.IsTrue (viewModel.HasError); + Assert.IsTrue (viewModel.ErrorMessage.Contains ("Test error occurred")); + Assert.IsTrue (viewModel.ErrorMessage.Contains ("Some package sources could not be reached.")); + } + + [Test] + public async Task Log_TwoPackageSourcesBothReportErrorWhenAggregateSourceSelected_AllPackageSourceCouldNotBeReachedErrorDisplayed () + { + CreateProject (); + AddTwoPackageSourcesToRegisteredSources (); + CreateViewModel (); + viewModel.SelectedPackageSource = viewModel.PackageSources.First (); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + var logger = viewModel as INuGetUILogger; + logger.Log (MessageLevel.Error, "Test error1 occurred"); + logger.Log (MessageLevel.Error, "Test error2 occurred"); + + Assert.IsTrue (viewModel.HasError); + Assert.IsTrue (viewModel.ErrorMessage.Contains ("Test error1 occurred")); + Assert.IsTrue (viewModel.ErrorMessage.Contains ("Test error2 occurred")); + Assert.IsTrue (viewModel.ErrorMessage.Contains ("All package sources could not be reached.")); + } + + [Test] + public async Task OnInstallingSelectedPackages_OnePackageSelected_PackageAddedToRecentPackages () + { + CreateProject (); + var source = AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("Test", "1.0"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.SelectedPackage = viewModel.PackageViewModels[0]; + + viewModel.OnInstallingSelectedPackages (); + + var package = viewModel.RecentPackagesRepository.GetPackages (source.Name).Single (); + Assert.AreEqual ("Test", package.Id); + } + + [Test] + public async Task OnInstallingSelectedPackages_OnePackageChecked_PackageAddedToRecentPackages () + { + CreateProject (); + var source = AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("A", "1.0"); + viewModel.PackageFeed.AddPackage ("B", "1.2"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + viewModel.PackageViewModels[1].IsChecked = true; + + viewModel.OnInstallingSelectedPackages (); + + var package = viewModel.RecentPackagesRepository.GetPackages (source.Name).Single (); + Assert.AreEqual ("B", package.Id); + } + + [Test] + public void IsOlderPackageInstalled_NoPackagesInstalledInProject_ReturnsFalse () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + + bool result = viewModel.IsOlderPackageInstalled ("Test", new NuGetVersion ("1.0")); + + Assert.IsFalse (result); + } + + [Test] + public async Task IsOlderPackageInstalled_SamePackageVersionInstalledInProject_ReturnsFalse () + { + CreateProject (); + var nugetProject = CreateNuGetProjectForProject (); + nugetProject.AddPackageReference ("Test", "1.0"); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + await viewModel.GetPackagesInstalledInProjectTask; + + bool result = viewModel.IsOlderPackageInstalled ("Test", new NuGetVersion ("1.0")); + + Assert.IsFalse (result); + } + + [Test] + public async Task IsOlderPackageInstalled_OlderPackageVersionInstalledInProject_ReturnsTrue () + { + CreateProject (); + var nugetProject = CreateNuGetProjectForProject (); + nugetProject.AddPackageReference ("Test", "1.0"); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + await viewModel.GetPackagesInstalledInProjectTask; + + bool result = viewModel.IsOlderPackageInstalled ("Test", new NuGetVersion ("1.1")); + + Assert.IsTrue (result); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FakePackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FakePackageFeed.cs new file mode 100644 index 0000000000..1fd176a313 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FakePackageFeed.cs @@ -0,0 +1,94 @@ +// +// FakePackageFeed.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.PackageManagement.UI; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; +using NuGet.Versioning; + +namespace MonoDevelop.PackageManagement.Tests +{ + class FakePackageFeed : IPackageFeed + { + public bool IsMultiSource { + get { return true; } + } + + public List<PackageIdentity> Packages = new List<PackageIdentity> (); + + public void AddPackage (string id, string version) + { + var package = new PackageIdentity (id, new NuGetVersion (version)); + Packages.Add (package); + } + + public string SearchText; + public SearchFilter SearchFilter; + + public Task<SearchResult<IPackageSearchMetadata>> SearchAsync (string searchText, SearchFilter filter, CancellationToken cancellationToken) + { + var results = new SearchResult<IPackageSearchMetadata> { + RefreshToken = new RefreshToken { }, + SourceSearchStatus = new Dictionary<string, LoadingStatus> { + { "Test", LoadingStatus.Loading } + } + }; + + SearchText = searchText; + SearchFilter = filter; + + return Task.FromResult (results); + } + + public Task<SearchResult<IPackageSearchMetadata>> RefreshSearchAsync (RefreshToken refreshToken, CancellationToken cancellationToken) + { + var items = Packages + .Select (package => PackageSearchMetadataBuilder.FromIdentity (package).Build ()) + .ToArray (); + + var results = SearchResult.FromItems (items); + results.NextToken = new ContinuationToken { }; + results.SourceSearchStatus = new Dictionary<string, LoadingStatus> { + { "Test", LoadingStatus.Ready } + }; + return Task.FromResult (results); + } + + public Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken) + { + var results = new SearchResult<IPackageSearchMetadata> (); + results.SourceSearchStatus = new Dictionary<string, LoadingStatus> { + { "Test", LoadingStatus.NoMoreItems } + }; + return Task.FromResult (results); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs index 983118b1b2..d6e03d0486 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs @@ -55,23 +55,45 @@ namespace MonoDevelop.PackageManagement IMonoDevelopSolutionManager solutionManager;
NuGetProject nugetProject;
IDotNetProject dotNetProject;
- NuGetProjectContext projectContext;
+ INuGetProjectContext projectContext;
List<PackageReference> packageReferences = new List<PackageReference> ();
AggregatePackageSourceErrorMessage aggregateErrorMessage;
NuGetPackageManager packageManager;
RecentNuGetPackagesRepository recentPackagesRepository;
- public AllPackagesViewModel (RecentNuGetPackagesRepository recentPackagesRepository)
+ public static AllPackagesViewModel Create (RecentNuGetPackagesRepository recentPackagesRepository)
{
+ var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (IdeApp.ProjectOperations.CurrentSelectedSolution);
+ var dotNetProject = new DotNetProjectProxy ((DotNetProject)IdeApp.ProjectOperations.CurrentSelectedProject);
+ return new AllPackagesViewModel (solutionManager, dotNetProject, recentPackagesRepository);
+ }
+
+ public AllPackagesViewModel (
+ IMonoDevelopSolutionManager solutionManager,
+ IDotNetProject dotNetProject,
+ RecentNuGetPackagesRepository recentPackagesRepository)
+ : this (
+ solutionManager,
+ dotNetProject,
+ new NuGetProjectContext (),
+ recentPackagesRepository)
+ {
+ }
+
+ public AllPackagesViewModel (
+ IMonoDevelopSolutionManager solutionManager,
+ IDotNetProject dotNetProject,
+ INuGetProjectContext projectContext,
+ RecentNuGetPackagesRepository recentPackagesRepository)
+ {
+ this.solutionManager = solutionManager;
+ this.dotNetProject = dotNetProject;
+ this.projectContext = projectContext;
this.recentPackagesRepository = recentPackagesRepository;
PackageViewModels = new ObservableCollection<PackageSearchResultViewModel> ();
CheckedPackageViewModels = new ObservableCollection<PackageSearchResultViewModel> ();
ErrorMessage = String.Empty;
- solutionManager = PackageManagementServices.Workspace.GetSolutionManager (IdeApp.ProjectOperations.CurrentSelectedSolution);
- projectContext = new NuGetProjectContext ();
- dotNetProject = new DotNetProjectProxy ((DotNetProject)IdeApp.ProjectOperations.CurrentSelectedProject);
-
packageManager = new NuGetPackageManager (
solutionManager.CreateSourceRepositoryProvider (),
solutionManager.Settings,
@@ -147,7 +169,7 @@ namespace MonoDevelop.PackageManagement }
}
- return packageSources.FirstOrDefault ();
+ return packageSources.FirstOrDefault (packageSource => !packageSource.IsAggregate);
}
void SaveActivePackageSource ()
@@ -239,11 +261,11 @@ namespace MonoDevelop.PackageManagement }
}
- void CreateReadPackagesTask()
+ protected virtual Task CreateReadPackagesTask()
{
var loader = currentLoader ?? CreatePackageLoader ();
cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource ();
- LoadPackagesAsync (loader, cancellationTokenSource.Token)
+ return LoadPackagesAsync (loader, cancellationTokenSource.Token)
.ContinueWith (t => OnPackagesRead (t, loader), TaskScheduler.FromCurrentSynchronizationContext ());
}
@@ -254,10 +276,9 @@ namespace MonoDevelop.PackageManagement false,
nugetProject);
- var packageFeed = new MultiSourcePackageFeed (context.SourceRepositories, this);
var loader = new PackageItemLoader (
context,
- packageFeed,
+ CreatePackageFeed (context.SourceRepositories),
SearchTerms,
IncludePrerelease
);
@@ -267,7 +288,12 @@ namespace MonoDevelop.PackageManagement return loader;
}
- static Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token)
+ protected virtual IPackageFeed CreatePackageFeed (IEnumerable<SourceRepository> sourceRepositories)
+ {
+ return new MultiSourcePackageFeed (sourceRepositories, this);
+ }
+
+ protected virtual Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token)
{
return Task.Run (async () => {
await loader.LoadNextAsync (null, token);
@@ -456,9 +482,9 @@ namespace MonoDevelop.PackageManagement packageReference.PackageIdentity.Version < version;
}
- void GetPackagesInstalledInProject ()
+ protected virtual Task GetPackagesInstalledInProject ()
{
- nugetProject
+ return nugetProject
.GetInstalledPackagesAsync (CancellationToken.None)
.ContinueWith (task => OnReadInstalledPackages (task), TaskScheduler.FromCurrentSynchronizationContext ());
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs index b2c1dbe650..b188928a4b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs @@ -45,7 +45,7 @@ namespace MonoDevelop.PackageManagement List<SourceRepository> secondarySources;
NuGetPackageManager packageManager;
NuGetProject project;
- NuGetProjectContext context;
+ INuGetProjectContext context;
IDotNetProject dotNetProject;
IEnumerable<NuGetProjectAction> actions;
@@ -53,7 +53,7 @@ namespace MonoDevelop.PackageManagement IEnumerable<SourceRepository> primarySources,
IMonoDevelopSolutionManager solutionManager,
IDotNetProject dotNetProject,
- NuGetProjectContext projectContext)
+ INuGetProjectContext projectContext)
: this (
primarySources,
null,
@@ -68,7 +68,7 @@ namespace MonoDevelop.PackageManagement IEnumerable<SourceRepository> secondarySources,
IMonoDevelopSolutionManager solutionManager,
IDotNetProject dotNetProject,
- NuGetProjectContext projectContext)
+ INuGetProjectContext projectContext)
{
this.primarySources = primarySources.ToList ();
this.secondarySources = secondarySources?.ToList ();
|