diff --git a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj index 2456da972..1ae0db688 100644 --- a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj +++ b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj @@ -104,6 +104,10 @@ False ..\..\lib\fluentnhibernate\NHibernate.ByteCode.Castle.dll + + False + ..\..\lib\nuget\NuGet.Core.dll + False ..\..\lib\nunit\nunit.framework.dll @@ -145,6 +149,8 @@ + + diff --git a/src/Orchard.Tests.Modules/Recipes/RecipeHandlers/ModuleRecipeHandlerTest.cs b/src/Orchard.Tests.Modules/Recipes/RecipeHandlers/ModuleRecipeHandlerTest.cs new file mode 100644 index 000000000..6103ef28c --- /dev/null +++ b/src/Orchard.Tests.Modules/Recipes/RecipeHandlers/ModuleRecipeHandlerTest.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Autofac; +using NuGet; +using NUnit.Framework; +using Orchard.Caching; +using Orchard.Core.Settings.Descriptor; +using Orchard.Core.Settings.Descriptor.Records; +using Orchard.Core.Settings.State; +using Orchard.Data.Migration; +using Orchard.Environment.Descriptor; +using Orchard.Environment.Descriptor.Models; +using Orchard.Environment.Extensions; +using Orchard.Environment.Extensions.Folders; +using Orchard.Environment.Extensions.Models; +using Orchard.Environment.Features; +using Orchard.Environment.State; +using Orchard.Events; +using Orchard.Packaging.GalleryServer; +using Orchard.Packaging.Models; +using Orchard.Packaging.Services; +using Orchard.Recipes.Models; +using Orchard.Recipes.RecipeHandlers; +using Orchard.Recipes.Services; +using Orchard.Tests.Environment.Extensions; +using Orchard.Tests.Environment.Features; +using Orchard.Tests.Stubs; +using IPackageManager = Orchard.Packaging.Services.IPackageManager; + +namespace Orchard.Tests.Modules.Recipes.RecipeHandlers { + [TestFixture] + public class ModuleRecipeHandlerTest : DatabaseEnabledTestsBase { + private ExtensionManagerTests.StubFolders _folders; + + protected override IEnumerable DatabaseTypes { + get { + return new[] { + typeof (ShellDescriptorRecord), + typeof (ShellFeatureRecord), + typeof (ShellParameterRecord), + }; + } + } + + public override void Register(ContainerBuilder builder) { + _folders = new ExtensionManagerTests.StubFolders(); + builder.RegisterInstance(_folders).As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType(); + builder.RegisterSource(new EventsRegistrationSource()); + } + + [Test] + public void ExecuteRecipeStepTest() { + _folders.Manifests.Add("SuperWiki", @" +Name: SuperWiki +Version: 1.0.3 +OrchardVersion: 1 +Features: + SuperWiki: + Description: My super wiki module for Orchard. +"); + + IShellDescriptorManager shellDescriptorManager = _container.Resolve(); + // No features enabled + shellDescriptorManager.UpdateShellDescriptor(0, + Enumerable.Empty(), + Enumerable.Empty()); + + ModuleRecipeHandler moduleRecipeHandler = _container.Resolve(); + + RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } }; + recipeContext.RecipeStep.Step.Add(new XAttribute("name", "SuperWiki")); + recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); + + IFeatureManager featureManager = _container.Resolve(); + IEnumerable enabledFeatures = featureManager.GetEnabledFeatures(); + Assert.That(enabledFeatures.Count(), Is.EqualTo(0)); + moduleRecipeHandler.ExecuteRecipeStep(recipeContext); + + enabledFeatures = featureManager.GetEnabledFeatures(); + Assert.That(enabledFeatures.FirstOrDefault(feature => feature.Id.Equals("SuperWiki")), Is.Not.Null); + Assert.That(enabledFeatures.Count(), Is.EqualTo(1)); + Assert.That(recipeContext.Executed, Is.True); + } + + [Test] + public void ExecuteRecipeStepNeedsNameTest() { + _folders.Manifests.Add("SuperWiki", @" +Name: SuperWiki +Version: 1.0.3 +OrchardVersion: 1 +Features: + SuperWiki: + Description: My super wiki module for Orchard. +"); + + ModuleRecipeHandler moduleRecipeHandler = _container.Resolve(); + + RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Module", Step = new XElement("SuperWiki") } }; + recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); + + Assert.Throws(typeof(InvalidOperationException), () => moduleRecipeHandler.ExecuteRecipeStep(recipeContext)); + } + + internal class StubPackagingSourceManager : IPackagingSourceManager { + public IEnumerable GetSources() { + return Enumerable.Empty(); + } + + public void AddSource(string feedTitle, string feedUrl) { + throw new NotImplementedException(); + } + + public void RemoveSource(int id) { + throw new NotImplementedException(); + } + + public IEnumerable GetExtensionList(PackagingSource packagingSource = null, Func, IQueryable> query = null) { + return new[] { + new PackagingEntry { + PackageId = "SuperWiki", + Title = "SuperWiki", + Version = "1.0.3" + } + }; + } + + public int GetExtensionCount(PackagingSource packagingSource = null, Func, IQueryable> query = null) { + throw new NotImplementedException(); + } + } + + internal class StubPackageManager : IPackageManager { + public PackageData Harvest(string extensionName) { + throw new NotImplementedException(); + } + + public PackageInfo Install(IPackage package, string location, string applicationPath) { + return null; + } + + public PackageInfo Install(string packageId, string version, string location, string applicationPath) { + return null; + } + + public void Uninstall(string packageId, string applicationPath) { + } + + public ExtensionDescriptor GetExtensionDescriptor(IPackage package) { + throw new NotImplementedException(); + } + } + + internal class StubDataMigrationManager : IDataMigrationManager { + public bool IsFeatureAlreadyInstalled(string feature) { + return true; + } + + public IEnumerable GetFeaturesThatNeedUpdate() { + return Enumerable.Empty(); + } + + public void Update(string feature) { + } + + public void Update(IEnumerable features) { + } + + public void Uninstall(string feature) { + } + } + } +} diff --git a/src/Orchard.Tests.Modules/Recipes/RecipeHandlers/ThemeRecipeHandlerTest.cs b/src/Orchard.Tests.Modules/Recipes/RecipeHandlers/ThemeRecipeHandlerTest.cs new file mode 100644 index 000000000..1f9a76754 --- /dev/null +++ b/src/Orchard.Tests.Modules/Recipes/RecipeHandlers/ThemeRecipeHandlerTest.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Hosting; +using System.Xml.Linq; +using Autofac; +using NUnit.Framework; +using Orchard.Caching; +using Orchard.Core.Settings.Descriptor; +using Orchard.Core.Settings.Descriptor.Records; +using Orchard.Core.Settings.State; +using Orchard.Data.Migration; +using Orchard.Environment.Descriptor; +using Orchard.Environment.Descriptor.Models; +using Orchard.Environment.Extensions; +using Orchard.Environment.Extensions.Folders; +using Orchard.Environment.Extensions.Models; +using Orchard.Environment.Features; +using Orchard.Environment.State; +using Orchard.Events; +using Orchard.FileSystems.VirtualPath; +using Orchard.Packaging.Services; +using Orchard.Recipes.Models; +using Orchard.Recipes.RecipeHandlers; +using Orchard.Tests.DisplayManagement.Descriptors; +using Orchard.Tests.Environment.Extensions; +using Orchard.Tests.Environment.Features; +using Orchard.Tests.Stubs; +using Orchard.Themes.Services; +using IPackageManager = Orchard.Packaging.Services.IPackageManager; + +namespace Orchard.Tests.Modules.Recipes.RecipeHandlers { + [TestFixture] + public class ThemeRecipeHandlerTest : DatabaseEnabledTestsBase { + private ExtensionManagerTests.StubFolders _folders; + + protected override IEnumerable DatabaseTypes { + get { + return new[] { + typeof (ShellDescriptorRecord), + typeof (ShellFeatureRecord), + typeof (ShellParameterRecord), + }; + } + } + + public override void Register(ContainerBuilder builder) { + var _testVirtualPathProvider = new StylesheetBindingStrategyTests.TestVirtualPathProvider(); + + _folders = new ExtensionManagerTests.StubFolders(); + builder.RegisterInstance(_folders).As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterInstance(_testVirtualPathProvider).As(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType(); + builder.RegisterSource(new EventsRegistrationSource()); + } + + [Test] + public void ExecuteRecipeStepTest() { + _folders.Manifests.Add("SuperWiki", @" +Name: SuperWiki +Version: 1.0.3 +OrchardVersion: 1 +Features: + SuperWiki: + Description: My super wiki theme for Orchard. +"); + + IShellDescriptorManager shellDescriptorManager = _container.Resolve(); + // No features enabled + shellDescriptorManager.UpdateShellDescriptor(0, + Enumerable.Empty(), + Enumerable.Empty()); + + ThemeRecipeHandler themeRecipeHandler = _container.Resolve(); + + RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } }; + recipeContext.RecipeStep.Step.Add(new XAttribute("name", "SuperWiki")); + recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); + + IFeatureManager featureManager = _container.Resolve(); + IEnumerable enabledFeatures = featureManager.GetEnabledFeatures(); + Assert.That(enabledFeatures.Count(), Is.EqualTo(0)); + themeRecipeHandler.ExecuteRecipeStep(recipeContext); + + // without setting enable no feature should be activated... + featureManager.GetEnabledFeatures(); + Assert.That(enabledFeatures.Count(), Is.EqualTo(0)); + + // Adding enable the feature should get active + recipeContext.RecipeStep.Step.Add(new XAttribute("enable", true)); + themeRecipeHandler.ExecuteRecipeStep(recipeContext); + + enabledFeatures = featureManager.GetEnabledFeatures(); + Assert.That(enabledFeatures.FirstOrDefault(feature => feature.Id.Equals("SuperWiki")), Is.Not.Null); + Assert.That(enabledFeatures.Count(), Is.EqualTo(1)); + Assert.That(recipeContext.Executed, Is.True); + } + + [Test] + public void ExecuteRecipeStepNeedsNameTest() { + _folders.Manifests.Add("SuperWiki", @" +Name: SuperWiki +Version: 1.0.3 +OrchardVersion: 1 +Features: + SuperWiki: + Description: My super wiki module for Orchard. +"); + + ThemeRecipeHandler themeRecipeHandler = _container.Resolve(); + + RecipeContext recipeContext = new RecipeContext { RecipeStep = new RecipeStep { Name = "Theme", Step = new XElement("SuperWiki") } }; + recipeContext.RecipeStep.Step.Add(new XAttribute("repository", "test")); + + Assert.Throws(typeof(InvalidOperationException), () => themeRecipeHandler.ExecuteRecipeStep(recipeContext)); + } + + internal class StubSiteThemeService : ISiteThemeService + { + public ExtensionDescriptor GetSiteTheme() { + throw new NotImplementedException(); + } + + public void SetSiteTheme(string themeName) { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ModuleRecipeHandler.cs b/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ModuleRecipeHandler.cs index adac6add1..9dabbb3f1 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ModuleRecipeHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ModuleRecipeHandler.cs @@ -65,43 +65,47 @@ namespace Orchard.Recipes.RecipeHandlers { if (name == null) { throw new InvalidOperationException("Name is required in a Module declaration in a recipe file."); } + // download and install module from the orchard feed or a custom feed if repository is specified. bool enforceVersion = version != null; bool installed = false; + PackagingSource packagingSource = _packagingSourceManager.GetSources().FirstOrDefault(); if (repository != null) { enforceVersion = false; packagingSource = new PackagingSource {FeedTitle = repository, FeedUrl = repository}; } - foreach (var packagingEntry in _packagingSourceManager.GetExtensionList(packagingSource)) { - if (String.Equals(packagingEntry.Title, name, StringComparison.OrdinalIgnoreCase)) { - if (enforceVersion && !String.Equals(packagingEntry.Version, version, StringComparison.OrdinalIgnoreCase)) { - continue; - } - var extensions = _extensionManager.AvailableExtensions(); - if (extensions.Where(extension => - DefaultExtensionTypes.IsModule(extension.ExtensionType) && - String.Equals(packagingEntry.Title, extension.Name, StringComparison.OrdinalIgnoreCase)).Any()) { - throw new InvalidOperationException(string.Format("Module {0} already exists.", name)); - } - _packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/")); - foreach ( - var features in - from extensionDescriptor in extensions - where String.Equals(extensionDescriptor.Name, packagingEntry.Title, StringComparison.OrdinalIgnoreCase) - select extensionDescriptor.Features.Select(f => f.Name).ToArray()) { - _featureManager.EnableFeatures(features); - _dataMigrationManager.Update(features); - installed = true; - } - break; + + if (_extensionManager.AvailableExtensions().Where(extension => + DefaultExtensionTypes.IsTheme(extension.ExtensionType) && + extension.Name.Equals(name, StringComparison.OrdinalIgnoreCase)).Any()) { + throw new InvalidOperationException(string.Format("Module {0} already exists.", name)); + } + + PackagingEntry packagingEntry = _packagingSourceManager.GetExtensionList(packagingSource, + packages => packages.Where(package => + package.PackageType.Equals(DefaultExtensionTypes.Module) && + package.Title.Equals(name, StringComparison.OrdinalIgnoreCase) && + (!enforceVersion || package.Version.Equals(version, StringComparison.OrdinalIgnoreCase)))) + .FirstOrDefault(); + + if (packagingEntry != null) { + _packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/")); + foreach (string[] features in + from extensionDescriptor in _extensionManager.AvailableExtensions() + where extensionDescriptor.Name.Equals(packagingEntry.Title, StringComparison.OrdinalIgnoreCase) + select extensionDescriptor.Features.Select(f => f.Name).ToArray()) { + + _featureManager.EnableFeatures(features); + _dataMigrationManager.Update(features); + + installed = true; } } if (!installed) { throw new InvalidOperationException(string.Format("Module {0} was not found in the specified location.", name)); } - recipeContext.Executed = true; } diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ThemeRecipeHandler.cs b/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ThemeRecipeHandler.cs index e51fd7bd2..5a1d701b5 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ThemeRecipeHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/ThemeRecipeHandler.cs @@ -25,11 +25,13 @@ namespace Orchard.Recipes.RecipeHandlers { IExtensionManager extensionManager, IThemeService themeService, ISiteThemeService siteThemeService) { + _packagingSourceManager = packagingSourceManager; _packageManager = packageManager; _extensionManager = extensionManager; _themeService = themeService; _siteThemeService = siteThemeService; + Logger = NullLogger.Instance; T = NullLocalizer.Instance; } @@ -71,36 +73,42 @@ namespace Orchard.Recipes.RecipeHandlers { if (name == null) { throw new InvalidOperationException("Name is required in a Theme declaration in a recipe file."); } + // download and install theme from the orchard feed or a custom feed if repository is specified. bool enforceVersion = version != null; bool installed = false; + PackagingSource packagingSource = _packagingSourceManager.GetSources().FirstOrDefault(); if (repository != null) { enforceVersion = false; packagingSource = new PackagingSource { FeedTitle = repository, FeedUrl = repository }; } - foreach (var packagingEntry in _packagingSourceManager.GetExtensionList(packagingSource)) { - if (String.Equals(packagingEntry.Title, name, StringComparison.OrdinalIgnoreCase)) { - if (enforceVersion && !String.Equals(packagingEntry.Version, version, StringComparison.OrdinalIgnoreCase)) { - continue; - } - if (_extensionManager.AvailableExtensions().Where(extension => - DefaultExtensionTypes.IsTheme(extension.ExtensionType) && - String.Equals(packagingEntry.Title, extension.Name, StringComparison.OrdinalIgnoreCase)).Any()) { - throw new InvalidOperationException(string.Format("Theme {0} already exists.", name)); - } - _packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/")); - if (current) { - _themeService.EnableThemeFeatures(packagingEntry.Title); - _siteThemeService.SetSiteTheme(packagingEntry.Title); - } - else if (enable) { - _themeService.EnableThemeFeatures(packagingEntry.Title); - } - installed = true; - break; + if (_extensionManager.AvailableExtensions().Where(extension => + DefaultExtensionTypes.IsTheme(extension.ExtensionType) && + extension.Name.Equals(name, StringComparison.OrdinalIgnoreCase)).Any()) { + throw new InvalidOperationException(string.Format("Theme {0} already exists.", name)); + } + + PackagingEntry packagingEntry = _packagingSourceManager.GetExtensionList(packagingSource, + packages => packages.Where(package => + package.PackageType.Equals(DefaultExtensionTypes.Theme) && + package.Title.Equals(name, StringComparison.OrdinalIgnoreCase) && + (!enforceVersion || package.Version.Equals(version, StringComparison.OrdinalIgnoreCase)))) + .FirstOrDefault(); + + if (packagingEntry != null) { + _packageManager.Install(packagingEntry.PackageId, packagingEntry.Version, packagingSource.FeedUrl, HostingEnvironment.MapPath("~/")); + + if (current) { + _themeService.EnableThemeFeatures(packagingEntry.Title); + _siteThemeService.SetSiteTheme(packagingEntry.Title); } + else if (enable) { + _themeService.EnableThemeFeatures(packagingEntry.Title); + } + + installed = true; } if (!installed) {