2010-01-21 16:54:00 +00:00
using System ;
using System.Collections.Generic ;
2010-04-02 15:17:13 -07:00
using Autofac ;
2010-01-21 16:54:00 +00:00
using JetBrains.Annotations ;
2010-06-08 12:05:29 -07:00
using Moq ;
2010-01-18 17:40:06 +00:00
using NUnit.Framework ;
2010-01-21 16:54:00 +00:00
using Orchard.ContentManagement ;
2010-08-23 16:14:10 -07:00
using Orchard.ContentManagement.Aspects ;
2010-01-21 16:54:00 +00:00
using Orchard.ContentManagement.Handlers ;
2010-06-08 12:05:29 -07:00
using Orchard.ContentManagement.MetaData ;
2010-01-21 16:54:00 +00:00
using Orchard.ContentManagement.Records ;
using Orchard.Core.Common.Models ;
2010-07-14 12:43:14 -07:00
using Orchard.Core.Routable ;
2010-07-13 02:52:02 -07:00
using Orchard.Core.Routable.Handlers ;
using Orchard.Core.Routable.Models ;
using Orchard.Core.Routable.Services ;
2010-08-23 16:14:10 -07:00
using Orchard.Data ;
2010-09-17 13:49:01 -07:00
using Orchard.DisplayManagement ;
using Orchard.DisplayManagement.Descriptors ;
using Orchard.DisplayManagement.Implementation ;
2010-08-23 16:14:10 -07:00
using Orchard.Environment ;
2010-10-12 12:21:46 -07:00
using Orchard.Environment.Extensions ;
2010-11-04 20:24:48 -07:00
using Orchard.Mvc ;
2010-08-23 16:14:10 -07:00
using Orchard.Security ;
2010-02-06 01:10:22 -08:00
using Orchard.Tests.Modules ;
2010-04-20 17:59:09 -07:00
using System.Web.Mvc ;
using System.Web.Routing ;
using Orchard.Tests.Stubs ;
2010-08-23 16:14:10 -07:00
using Orchard.UI.Notify ;
2010-01-18 17:40:06 +00:00
2010-08-26 07:32:45 -07:00
namespace Orchard.Core.Tests.Routable.Services {
2010-01-18 17:40:06 +00:00
[TestFixture]
2010-01-21 16:54:00 +00:00
public class RoutableServiceTests : DatabaseEnabledTestsBase {
2010-01-18 17:40:06 +00:00
[SetUp]
2010-01-21 16:54:00 +00:00
public override void Init ( ) {
base . Init ( ) ;
_routableService = _container . Resolve < IRoutableService > ( ) ;
2010-01-18 17:40:06 +00:00
}
2010-01-21 16:54:00 +00:00
public override void Register ( ContainerBuilder builder ) {
2010-04-02 15:17:13 -07:00
builder . RegisterType < DefaultContentManager > ( ) . As < IContentManager > ( ) ;
2010-05-16 23:34:08 -07:00
builder . RegisterType < DefaultContentManagerSession > ( ) . As < IContentManagerSession > ( ) ;
2010-06-08 12:05:29 -07:00
builder . RegisterInstance ( new Mock < IContentDefinitionManager > ( ) . Object ) ;
2010-08-23 16:14:10 -07:00
builder . RegisterInstance ( new Mock < ITransactionManager > ( ) . Object ) ;
builder . RegisterInstance ( new Mock < IAuthorizer > ( ) . Object ) ;
builder . RegisterInstance ( new Mock < INotifier > ( ) . Object ) ;
2010-10-14 12:03:28 -07:00
builder . RegisterInstance ( new Mock < IContentDisplay > ( ) . Object ) ;
2010-11-04 20:24:48 -07:00
builder . RegisterType < StubHttpContextAccessor > ( ) . As < IHttpContextAccessor > ( ) ;
2010-11-24 18:57:42 -08:00
builder . RegisterType < WorkContextAccessor > ( ) . As < IWorkContextAccessor > ( ) ;
2010-08-23 16:14:10 -07:00
builder . RegisterType < OrchardServices > ( ) . As < IOrchardServices > ( ) ;
2010-05-16 23:34:08 -07:00
2010-04-02 15:17:13 -07:00
builder . RegisterType < ThingHandler > ( ) . As < IContentHandler > ( ) ;
2010-04-20 17:59:09 -07:00
builder . RegisterType < StuffHandler > ( ) . As < IContentHandler > ( ) ;
2010-04-02 15:17:13 -07:00
builder . RegisterType < RoutableService > ( ) . As < IRoutableService > ( ) ;
2010-07-14 12:43:14 -07:00
builder . RegisterType < RoutablePathConstraint > ( ) . As < IRoutablePathConstraint > ( ) ;
2010-09-17 13:49:01 -07:00
builder . RegisterType < DefaultShapeTableManager > ( ) . As < IShapeTableManager > ( ) ;
builder . RegisterType < DefaultShapeFactory > ( ) . As < IShapeFactory > ( ) ;
2010-04-20 17:59:09 -07:00
builder . RegisterType < DefaultContentQuery > ( ) . As < IContentQuery > ( ) ;
builder . RegisterInstance ( new UrlHelper ( new RequestContext ( new StubHttpContext ( "~/" ) , new RouteData ( ) ) ) ) . As < UrlHelper > ( ) ;
2010-07-23 01:01:49 -07:00
builder . RegisterType < RoutePartHandler > ( ) . As < IContentHandler > ( ) ;
2010-10-12 12:21:46 -07:00
builder . RegisterType < StubExtensionManager > ( ) . As < IExtensionManager > ( ) ;
2010-10-14 11:26:42 -07:00
builder . RegisterType < DefaultContentDisplay > ( ) . As < IContentDisplay > ( ) ;
2010-01-21 16:54:00 +00:00
}
2010-01-18 17:40:06 +00:00
private IRoutableService _routableService ;
2010-01-21 16:54:00 +00:00
[Test]
public void InvalidCharactersShouldBeReplacedByADash ( ) {
var contentManager = _container . Resolve < IContentManager > ( ) ;
2010-09-02 15:11:33 -07:00
var thing = contentManager . Create < Thing > ( "thing" , t = > {
2010-07-23 01:01:49 -07:00
t . As < RoutePart > ( ) . Record = new RoutePartRecord ( ) ;
2010-11-16 11:16:19 -08:00
t . Title = "Please do not use any of the following characters in your slugs: \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\", \"\"\", \"<\", \">\"" ;
2010-01-21 16:54:00 +00:00
} ) ;
2010-08-24 11:41:41 -07:00
_routableService . FillSlugFromTitle ( thing . As < RoutePart > ( ) ) ;
2010-01-21 16:54:00 +00:00
2010-11-16 11:16:19 -08:00
Assert . That ( thing . Slug , Is . EqualTo ( "please-do-not-use-any-of-the-following-characters-in-your-slugs" ) ) ;
2010-08-26 07:32:45 -07:00
}
[Test]
public void SlashInSlugIsAllowed ( ) {
Assert . That ( _routableService . IsSlugValid ( "some/page" ) , Is . True ) ;
2010-01-21 16:54:00 +00:00
}
2010-10-14 16:55:09 -07:00
[Test]
public void DotsAroundSlugAreAllowed ( ) {
Assert . That ( _routableService . IsSlugValid ( ".slug" ) , Is . False ) ;
Assert . That ( _routableService . IsSlugValid ( "slug." ) , Is . False ) ;
Assert . That ( _routableService . IsSlugValid ( "slug.slug" ) , Is . True ) ;
}
2010-04-21 10:01:57 -07:00
[Test]
public void EmptySlugsShouldBeConsideredValid ( ) {
// so that automatic generation on Publish occurs
Assert . That ( _routableService . IsSlugValid ( null ) , Is . True ) ;
Assert . That ( _routableService . IsSlugValid ( String . Empty ) , Is . True ) ;
Assert . That ( _routableService . IsSlugValid ( " " ) , Is . True ) ;
}
[Test]
public void InvalidCharacterShouldBeRefusedInSlugs ( ) {
Assert . That ( _routableService . IsSlugValid ( "aaaa-_aaaa" ) , Is . True ) ;
2010-08-26 07:32:45 -07:00
foreach ( var c in @":?#[]@!$&'()*+,;= " ) {
2010-04-21 10:01:57 -07:00
Assert . That ( _routableService . IsSlugValid ( "a" + c + "b" ) , Is . False ) ;
}
}
2010-05-16 23:34:08 -07:00
2010-01-21 16:54:00 +00:00
[Test]
public void VeryLongStringTruncatedTo1000Chars ( ) {
2010-01-27 07:12:27 +00:00
var veryVeryLongTitle = "this is a very long title..." ;
2010-01-21 16:54:00 +00:00
for ( var i = 0 ; i < 100 ; i + + )
veryVeryLongTitle + = "aaaaaaaaaa" ;
2010-11-13 01:52:53 -08:00
var thing = CreateRoutePartFromScratch ( veryVeryLongTitle ) ;
2010-08-24 11:41:41 -07:00
_routableService . FillSlugFromTitle ( thing ) ;
2010-01-21 16:54:00 +00:00
Assert . That ( veryVeryLongTitle . Length , Is . AtLeast ( 1001 ) ) ;
Assert . That ( thing . Slug . Length , Is . EqualTo ( 1000 ) ) ;
}
2010-01-22 22:25:52 +00:00
[Test]
public void NoExistingLikeSlugsGeneratesSameSlug ( ) {
2010-11-13 01:52:53 -08:00
string slug = _routableService . GenerateUniqueSlug ( CreateRoutePartFromScratch ( "woohoo" ) , null ) ;
2010-01-22 22:25:52 +00:00
Assert . That ( slug , Is . EqualTo ( "woohoo" ) ) ;
}
[Test]
public void ExistingSingleLikeSlugThatsAConflictGeneratesADash2 ( ) {
2010-11-13 01:52:53 -08:00
string slug = _routableService . GenerateUniqueSlug ( CreateRoutePartFromScratch ( "woohoo" ) , new List < string > { "woohoo" } ) ;
2010-01-22 22:25:52 +00:00
Assert . That ( slug , Is . EqualTo ( "woohoo-2" ) ) ;
}
[Test]
public void ExistingSingleLikeSlugThatsNotAConflictGeneratesSameSlug ( ) {
2010-11-13 01:52:53 -08:00
string slug = _routableService . GenerateUniqueSlug ( CreateRoutePartFromScratch ( "woohoo" ) , new List < string > { "woohoo-2" } ) ;
2010-01-22 22:25:52 +00:00
Assert . That ( slug , Is . EqualTo ( "woohoo" ) ) ;
}
[Test]
public void ExistingLikeSlugsWithAConflictGeneratesADashVNext ( ) {
2010-11-13 01:52:53 -08:00
string slug = _routableService . GenerateUniqueSlug ( CreateRoutePartFromScratch ( "woohoo" ) , new List < string > { "woohoo" , "woohoo-2" } ) ;
2010-01-22 22:25:52 +00:00
Assert . That ( slug , Is . EqualTo ( "woohoo-3" ) ) ;
}
[Test]
public void ExistingSlugsWithVersionGapsAndNoMatchGeneratesSameSlug ( ) {
2010-11-13 01:52:53 -08:00
string slug = _routableService . GenerateUniqueSlug ( CreateRoutePartFromScratch ( "woohoo" ) , new List < string > { "woohoo-2" , "woohoo-4" , "woohoo-5" } ) ;
2010-01-22 22:25:52 +00:00
Assert . That ( slug , Is . EqualTo ( "woohoo" ) ) ;
}
[Test]
public void ExistingSlugsWithVersionGapsAndAMatchGeneratesADash2 ( ) {
2010-11-13 01:52:53 -08:00
string slug = _routableService . GenerateUniqueSlug ( CreateRoutePartFromScratch ( "woohoo-2" ) , new List < string > { "woohoo-2" , "woohoo-4" , "woohoo-5" } ) ;
2010-01-22 22:25:52 +00:00
Assert . That ( slug , Is . EqualTo ( "woohoo-2-2" ) ) ;
}
2010-01-27 07:12:27 +00:00
[Test]
2010-11-13 01:52:53 -08:00
public void SlugIsGeneratedLowerCased ( ) {
var thing = CreateRoutePartFromScratch ( "This Is Some Interesting Title" ) ;
2010-08-24 11:41:41 -07:00
_routableService . FillSlugFromTitle ( thing ) ;
2010-01-27 07:12:27 +00:00
Assert . That ( thing . Slug , Is . EqualTo ( "this-is-some-interesting-title" ) ) ;
}
2010-08-23 16:14:10 -07:00
[Test]
public void SlugInConflictWithAnExistingItemsPathIsVersioned ( ) {
2010-11-13 01:52:53 -08:00
CreateRoutePartFromScratch ( "bar" , "bar" , "foo" ) ;
var thing2 = CreateRoutePartFromScratch ( "fooslashbar" , "foo/bar" ) ;
Assert . That ( thing2 . Path , Is . EqualTo ( "foo/bar-2" ) ) ;
}
[Test]
public void GeneratedSlugInConflictInSameContaierPathIsVersioned ( ) {
var thing1 = CreateRoutePartFromScratch ( "Foo" , "" , "bar" ) ;
var thing2 = CreateRoutePartWithExistingContainer ( "Foo" , thing1 . As < ICommonPart > ( ) . Container ) ;
Assert . That ( thing2 . Path , Is . EqualTo ( "bar/foo-2" ) ) ;
2010-11-16 00:27:54 -08:00
Assert . That ( thing2 . Slug , Is . EqualTo ( "foo-2" ) ) ;
2010-11-13 01:52:53 -08:00
}
[Test]
public void GivenSlugInConflictInSameContaierPathIsVersioned ( ) {
var thing1 = CreateRoutePartFromScratch ( "Hi" , "foo" , "bar" ) ;
var thing2 = CreateRoutePartWithExistingContainer ( "There" , thing1 . As < ICommonPart > ( ) . Container , "foo" ) ;
Assert . That ( thing2 . Path , Is . EqualTo ( "bar/foo-2" ) ) ;
2010-11-16 00:27:54 -08:00
Assert . That ( thing2 . Slug , Is . EqualTo ( "foo-2" ) ) ;
2010-11-13 01:52:53 -08:00
}
2010-04-20 17:59:09 -07:00
2010-11-13 01:52:53 -08:00
[Test]
public void GeneratedSlugInConflictInDifferentContaierPathIsNotVersioned ( ) {
var thing1 = CreateRoutePartFromScratch ( "Foo" , "" , "rab" ) ;
var thing2 = CreateRoutePartFromScratch ( "Foo" , "" , "bar" ) ;
Assert . That ( thing1 . Path , Is . EqualTo ( "rab/foo" ) ) ;
Assert . That ( thing2 . Path , Is . EqualTo ( "bar/foo" ) ) ;
Assert . That ( thing1 . Slug , Is . EqualTo ( "foo" ) ) ;
Assert . That ( thing2 . Slug , Is . EqualTo ( "foo" ) ) ;
}
private RoutePart CreateRoutePartWithExistingContainer ( string title , IContent container , string slug = "" ) {
var contentManager = _container . Resolve < IContentManager > ( ) ;
return contentManager . Create < Thing > ( "thing" , t = > {
t . As < RoutePart > ( ) . Record = new RoutePartRecord ( ) ;
t . Title = title ;
if ( ! string . IsNullOrWhiteSpace ( slug ) )
t . As < RoutePart > ( ) . Slug = slug ;
if ( container ! = null )
t . As < ICommonPart > ( ) . Container = container ;
} ) . As < RoutePart > ( ) ;
2010-04-20 17:59:09 -07:00
}
2010-11-13 01:52:53 -08:00
private RoutePart CreateRoutePartFromScratch ( string title , string slug = "" , string containerPath = "" ) {
2010-04-20 17:59:09 -07:00
var contentManager = _container . Resolve < IContentManager > ( ) ;
2010-09-02 15:11:33 -07:00
return contentManager . Create < Thing > ( "thing" , t = > {
2010-11-13 01:52:53 -08:00
t . As < RoutePart > ( ) . Record = new RoutePartRecord ( ) ;
if ( ! string . IsNullOrWhiteSpace ( slug ) )
t . As < RoutePart > ( ) . Slug = slug ;
t . Title = title ;
if ( ! string . IsNullOrWhiteSpace ( containerPath ) ) {
t . As < ICommonPart > ( ) . Container = contentManager . Create < Thing > ( "thing" , tt = > {
tt . As < RoutePart > ( ) . Path = containerPath ;
tt . As < RoutePart > ( ) . Slug = containerPath ;
tt . As < RoutePart > ( ) . Title = "Test Container" ;
} ) ;
}
} ) . As < RoutePart > ( ) ;
2010-04-20 17:59:09 -07:00
}
2010-01-21 16:54:00 +00:00
protected override IEnumerable < Type > DatabaseTypes {
get {
return new [ ] {
2010-07-23 01:01:49 -07:00
typeof ( RoutePartRecord ) ,
2010-05-20 11:00:44 -07:00
typeof ( ContentTypeRecord ) ,
2010-01-21 16:54:00 +00:00
typeof ( ContentItemRecord ) ,
typeof ( ContentItemVersionRecord ) ,
2010-07-22 12:52:16 -07:00
typeof ( CommonPartRecord ) ,
typeof ( CommonPartVersionRecord ) ,
2010-01-21 16:54:00 +00:00
} ;
}
}
[UsedImplicitly]
public class ThingHandler : ContentHandler {
2010-05-16 23:34:08 -07:00
public ThingHandler ( ) {
2010-09-02 15:11:33 -07:00
Filters . Add ( new ActivatingFilter < Thing > ( "thing" ) ) ;
Filters . Add ( new ActivatingFilter < ContentPart < CommonPartVersionRecord > > ( "thing" ) ) ;
Filters . Add ( new ActivatingFilter < CommonPart > ( "thing" ) ) ;
Filters . Add ( new ActivatingFilter < RoutePart > ( "thing" ) ) ;
2010-01-21 16:54:00 +00:00
}
}
public class Thing : ContentPart {
public string Title {
2010-07-23 01:01:49 -07:00
get { return this . As < RoutePart > ( ) . Title ; }
set { this . As < RoutePart > ( ) . Title = value ; }
2010-01-21 16:54:00 +00:00
}
public string Slug {
2010-07-23 01:01:49 -07:00
get { return this . As < RoutePart > ( ) . Slug ; }
set { this . As < RoutePart > ( ) . Slug = value ; }
2010-01-21 16:54:00 +00:00
}
}
2010-05-16 23:34:08 -07:00
2010-04-20 17:59:09 -07:00
[UsedImplicitly]
2010-05-16 23:34:08 -07:00
public class StuffHandler : ContentHandler {
public StuffHandler ( ) {
2010-09-02 15:11:33 -07:00
Filters . Add ( new ActivatingFilter < Stuff > ( "stuff" ) ) ;
Filters . Add ( new ActivatingFilter < ContentPart < CommonPartVersionRecord > > ( "stuff" ) ) ;
Filters . Add ( new ActivatingFilter < CommonPart > ( "stuff" ) ) ;
Filters . Add ( new ActivatingFilter < RoutePart > ( "stuff" ) ) ;
2010-04-20 17:59:09 -07:00
}
}
2010-05-16 23:34:08 -07:00
public class Stuff : ContentPart {
public string Title {
2010-07-23 01:01:49 -07:00
get { return this . As < RoutePart > ( ) . Title ; }
set { this . As < RoutePart > ( ) . Title = value ; }
2010-04-20 17:59:09 -07:00
}
2010-05-16 23:34:08 -07:00
public string Slug {
2010-07-23 01:01:49 -07:00
get { return this . As < RoutePart > ( ) . Slug ; }
set { this . As < RoutePart > ( ) . Slug = value ; }
2010-04-20 17:59:09 -07:00
}
}
2010-01-18 17:40:06 +00:00
}
}