2017-07-20 11:21:28 +02:00
using System ;
2016-06-07 12:20:10 +02:00
using System.Collections ;
2013-09-06 20:21:47 +02:00
using System.Collections.Generic ;
2016-06-07 12:20:10 +02:00
using System.ComponentModel ;
2012-08-09 04:15:35 +06:00
using System.Configuration ;
2012-07-26 21:12:54 +06:00
using System.IO ;
2013-08-23 16:22:26 +02:00
using System.Linq ;
2012-07-26 21:12:54 +06:00
using System.Reflection ;
2016-11-03 10:39:21 +01:00
using System.Threading ;
2016-06-07 12:20:10 +02:00
using NUnit.Framework ;
2012-11-29 09:07:14 -01:00
using Umbraco.Core ;
using Umbraco.Core.IO ;
2016-06-07 12:20:10 +02:00
using Umbraco.Core.Models.EntityBase ;
2012-07-26 21:12:54 +06:00
2012-07-31 00:02:27 +06:00
namespace Umbraco.Tests.TestHelpers
2012-08-17 04:27:47 +06:00
{
2015-01-22 15:16:10 +11:00
/// <summary>
2017-07-20 11:21:28 +02:00
/// Common helper properties and methods useful to testing
/// </summary>
public static class TestHelper
{
/// <summary>
/// Gets the current assembly directory.
/// </summary>
/// <value>The assembly directory.</value>
static public string CurrentAssemblyDirectory
{
get
{
var codeBase = typeof ( TestHelper ) . Assembly . CodeBase ;
var uri = new Uri ( codeBase ) ;
var path = uri . LocalPath ;
return Path . GetDirectoryName ( path ) ;
}
}
/// <summary>
/// Maps the given <paramref name="relativePath"/> making it rooted on <see cref="CurrentAssemblyDirectory"/>. <paramref name="relativePath"/> must start with <code>~/</code>
/// </summary>
/// <param name="relativePath">The relative path.</param>
/// <returns></returns>
public static string MapPathForTest ( string relativePath )
{
if ( ! relativePath . StartsWith ( "~/" ) )
throw new ArgumentException ( "relativePath must start with '~/'" , "relativePath" ) ;
return relativePath . Replace ( "~/" , CurrentAssemblyDirectory + "/" ) ;
}
public static void InitializeContentDirectories ( )
2012-11-29 09:07:14 -01:00
{
2013-07-10 17:28:15 +10:00
CreateDirectories ( new [ ] { SystemDirectories . Masterpages , SystemDirectories . MvcViews , SystemDirectories . Media , SystemDirectories . AppPlugins } ) ;
2012-11-29 09:07:14 -01:00
}
2017-07-20 11:21:28 +02:00
public static void CleanContentDirectories ( )
{
CleanDirectories ( new [ ] { SystemDirectories . Masterpages , SystemDirectories . MvcViews , SystemDirectories . Media } ) ;
}
2012-11-29 09:07:14 -01:00
2017-07-20 11:21:28 +02:00
public static void CreateDirectories ( string [ ] directories )
2012-11-29 09:07:14 -01:00
{
foreach ( var directory in directories )
{
var directoryInfo = new DirectoryInfo ( IOHelper . MapPath ( directory ) ) ;
if ( directoryInfo . Exists = = false )
Directory . CreateDirectory ( IOHelper . MapPath ( directory ) ) ;
}
}
2017-07-20 11:21:28 +02:00
public static void CleanDirectories ( string [ ] directories )
{
var preserves = new Dictionary < string , string [ ] >
{
{ SystemDirectories . Masterpages , new [ ] { "dummy.txt" } } ,
{ SystemDirectories . MvcViews , new [ ] { "dummy.txt" } }
} ;
2012-11-29 09:07:14 -01:00
foreach ( var directory in directories )
{
var directoryInfo = new DirectoryInfo ( IOHelper . MapPath ( directory ) ) ;
2013-09-06 20:21:47 +02:00
var preserve = preserves . ContainsKey ( directory ) ? preserves [ directory ] : null ;
2012-11-29 09:07:14 -01:00
if ( directoryInfo . Exists )
2013-09-06 20:21:47 +02:00
directoryInfo . GetFiles ( ) . Where ( x = > preserve = = null | | preserve . Contains ( x . Name ) = = false ) . ForEach ( x = > x . Delete ( ) ) ;
2012-11-29 09:07:14 -01:00
}
}
2013-08-23 16:22:26 +02:00
2017-07-20 11:21:28 +02:00
public static void CleanUmbracoSettingsConfig ( )
2013-08-23 16:22:26 +02:00
{
var currDir = new DirectoryInfo ( CurrentAssemblyDirectory ) ;
var umbracoSettingsFile = Path . Combine ( currDir . Parent . Parent . FullName , "config" , "umbracoSettings.config" ) ;
if ( File . Exists ( umbracoSettingsFile ) )
File . Delete ( umbracoSettingsFile ) ;
}
2016-06-07 12:20:10 +02:00
public static void AssertAllPropertyValuesAreEquals ( object actual , object expected , string dateTimeFormat = null , Func < IEnumerable , IEnumerable > sorter = null , string [ ] ignoreProperties = null )
{
var properties = expected . GetType ( ) . GetProperties ( ) ;
foreach ( var property in properties )
{
//ignore properties that are attributed with this
var att = property . GetCustomAttribute < EditorBrowsableAttribute > ( false ) ;
if ( att ! = null & & att . State = = EditorBrowsableState . Never )
continue ;
if ( ignoreProperties ! = null & & ignoreProperties . Contains ( property . Name ) )
continue ;
var expectedValue = property . GetValue ( expected , null ) ;
var actualValue = property . GetValue ( actual , null ) ;
if ( ( ( actualValue is string ) = = false ) & & actualValue is IEnumerable )
{
AssertListsAreEquals ( property , ( IEnumerable ) actualValue , ( IEnumerable ) expectedValue , dateTimeFormat , sorter ) ;
}
else if ( dateTimeFormat . IsNullOrWhiteSpace ( ) = = false & & actualValue is DateTime )
{
2016-10-10 19:18:49 +02:00
// round to second else in some cases tests can fail ;-(
var expectedDateTime = ( DateTime ) expectedValue ;
expectedDateTime = expectedDateTime . AddTicks ( - ( expectedDateTime . Ticks % TimeSpan . TicksPerSecond ) ) ;
var actualDateTime = ( DateTime ) actualValue ;
actualDateTime = actualDateTime . AddTicks ( - ( actualDateTime . Ticks % TimeSpan . TicksPerSecond ) ) ;
Assert . AreEqual ( expectedDateTime . ToString ( dateTimeFormat ) , actualDateTime . ToString ( dateTimeFormat ) , "Property {0}.{1} does not match. Expected: {2} but was: {3}" , property . DeclaringType . Name , property . Name , expectedValue , actualValue ) ;
2016-06-07 12:20:10 +02:00
}
else
{
Assert . AreEqual ( expectedValue , actualValue , "Property {0}.{1} does not match. Expected: {2} but was: {3}" , property . DeclaringType . Name , property . Name , expectedValue , actualValue ) ;
}
}
}
private static void AssertListsAreEquals ( PropertyInfo property , IEnumerable actualList , IEnumerable expectedList , string dateTimeFormat , Func < IEnumerable , IEnumerable > sorter )
{
if ( sorter = = null )
{
//this is pretty hackerific but saves us some code to write
sorter = enumerable = >
{
//semi-generic way of ensuring any collection of IEntity are sorted by Ids for comparison
var entities = enumerable . OfType < IEntity > ( ) . ToList ( ) ;
if ( entities . Count > 0 )
{
return entities . OrderBy ( x = > x . Id ) ;
}
else
{
return enumerable ;
}
} ;
2017-07-20 11:21:28 +02:00
}
2016-06-07 12:20:10 +02:00
var actualListEx = sorter ( actualList ) . Cast < object > ( ) . ToList ( ) ;
var expectedListEx = sorter ( expectedList ) . Cast < object > ( ) . ToList ( ) ;
if ( actualListEx . Count ! = expectedListEx . Count )
Assert . Fail ( "Collection {0}.{1} does not match. Expected IEnumerable containing {2} elements but was IEnumerable containing {3} elements" , property . PropertyType . Name , property . Name , expectedListEx . Count , actualListEx . Count ) ;
for ( int i = 0 ; i < actualListEx . Count ; i + + )
{
var actualValue = actualListEx [ i ] ;
var expectedValue = expectedListEx [ i ] ;
if ( ( ( actualValue is string ) = = false ) & & actualValue is IEnumerable )
{
AssertListsAreEquals ( property , ( IEnumerable ) actualValue , ( IEnumerable ) expectedValue , dateTimeFormat , sorter ) ;
}
else if ( dateTimeFormat . IsNullOrWhiteSpace ( ) = = false & & actualValue is DateTime )
{
Assert . AreEqual ( ( ( DateTime ) expectedValue ) . ToString ( dateTimeFormat ) , ( ( DateTime ) actualValue ) . ToString ( dateTimeFormat ) , "Property {0}.{1} does not match. Expected: {2} but was: {3}" , property . DeclaringType . Name , property . Name , expectedValue , actualValue ) ;
}
else
{
Assert . AreEqual ( expectedValue , actualValue , "Property {0}.{1} does not match. Expected: {2} but was: {3}" , property . DeclaringType . Name , property . Name , expectedValue , actualValue ) ;
}
}
}
2016-11-03 10:39:21 +01:00
public static void DeleteDirectory ( string path )
{
Try ( ( ) = >
{
2016-10-31 11:08:28 +01:00
if ( Directory . Exists ( path ) = = false ) return ;
2016-11-03 10:39:21 +01:00
foreach ( var file in Directory . EnumerateFiles ( path , "*" , SearchOption . AllDirectories ) )
File . Delete ( file ) ;
} ) ;
Try ( ( ) = >
{
2016-10-31 11:08:28 +01:00
if ( Directory . Exists ( path ) = = false ) return ;
2016-11-03 10:39:21 +01:00
Directory . Delete ( path , true ) ;
} ) ;
}
public static void TryAssert ( Action action , int maxTries = 5 , int waitMilliseconds = 200 )
{
Try < AssertionException > ( action , maxTries , waitMilliseconds ) ;
}
public static void Try ( Action action , int maxTries = 5 , int waitMilliseconds = 200 )
{
Try < Exception > ( action , maxTries , waitMilliseconds ) ;
}
2013-08-23 16:22:26 +02:00
2016-11-03 10:39:21 +01:00
public static void Try < T > ( Action action , int maxTries = 5 , int waitMilliseconds = 200 )
where T : Exception
{
var tries = 0 ;
while ( true )
{
try
{
action ( ) ;
break ;
}
catch ( T )
{
if ( tries + + > maxTries )
throw ;
Thread . Sleep ( waitMilliseconds ) ;
}
}
}
2016-06-07 12:20:10 +02:00
}
2017-07-20 11:21:28 +02:00
}