diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index 7d9d59c08c..c501e965ae 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -54,15 +55,39 @@ namespace Umbraco.Core.Persistence.Migrations.Initial {34, typeof (TaskTypeDto)}, {35, typeof (TaskDto)}, {36, typeof (ContentType2ContentTypeDto)}, - { - 37, - typeof (ContentTypeAllowedContentTypeDto) - }, + {37, typeof (ContentTypeAllowedContentTypeDto)}, {38, typeof (User2AppDto)}, {39, typeof (User2NodeNotifyDto)}, {40, typeof (User2NodePermissionDto)} }; #endregion + /// + /// Drops all Umbraco tables in the db + /// + internal void UninstallDatabaseSchema() + { + LogHelper.Info("Start UninstallDatabaseSchema"); + + foreach (var item in OrderedTables.OrderByDescending(x => x.Key)) + { + var tableNameAttribute = item.Value.FirstAttribute(); + + string tableName = tableNameAttribute == null ? item.Value.Name : tableNameAttribute.Value; + + LogHelper.Info("Uninstall" + tableName); + + try + { + _database.DropTable(tableName); + } + catch (Exception ex) + { + //swallow this for now, not sure how best to handle this with diff databases... though this is internal + // and only used for unit tests. If this fails its because the table doesn't exist... generally! + LogHelper.Error("Could not drop table " + tableName, ex); + } + } + } public DatabaseSchemaCreation(Database database) { diff --git a/src/Umbraco.Tests/Integration/CreateContent.cs b/src/Umbraco.Tests/Integration/CreateContent.cs new file mode 100644 index 0000000000..c4164cc3ca --- /dev/null +++ b/src/Umbraco.Tests/Integration/CreateContent.cs @@ -0,0 +1,155 @@ +using System; +using System.Runtime.InteropServices; +using System.Threading; +using NUnit.Framework; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Integration +{ + [Ignore("We don't want to run Selenium tests on TeamCity")] + [TestFixture] + public class CreateContent : BaseSeleniumTest + { + [SetUp] + public override void Initialize() + { + base.Initialize(); + } + + [TearDown] + public void TearDown() + { + base.TearDown(); + } + + [Test] + public void Install_StarterKit_And_Create_Textpage() + { + // Login to Umbraco + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/login.aspx?redir="); + Driver.FindElement(By.Id("lname")).Clear(); + Driver.FindElement(By.Id("lname")).SendKeys("admin"); + Driver.FindElement(By.Id("passw")).Clear(); + Driver.FindElement(By.Id("passw")).SendKeys("test"); + Driver.FindElement(By.Id("Button1")).Click(); + Thread.Sleep(500); + + // Install starter kit + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/umbraco.aspx#developer"); + Thread.Sleep(2000); + + var builder = new Actions(Driver); + var packagesNode = Driver.FindElement(By.XPath("//*[@id='init'][3]")); + builder.MoveToElement(packagesNode).DoubleClick().Build().Perform(); + Thread.Sleep(500); + + var installStarterKitNode = Driver.FindElement(By.XPath("(//li[@id='-1']/a/div)[4]")); + builder.MoveToElement(installStarterKitNode).Click().Build().Perform(); + Thread.Sleep(500); + + var rightFrame = Driver.FindElement(By.XPath("//*[@id='right']")); + Driver.SwitchTo().Frame(rightFrame); + Thread.Sleep(500); + + var simpleKit = Driver.FindElement(By.XPath("/html/body/form/div[2]/div[2]/div/div/div/div/div[4]/nav/ul/li[1]/a")); + builder.MoveToElement(simpleKit).Click().Build().Perform(); + Thread.Sleep(6000); + + // Create new content + Driver.SwitchTo().DefaultContent(); + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/umbraco.aspx#content"); + Thread.Sleep(500); + + var contentNode = Driver.FindElement(By.XPath("//*[@id = 'JTree_TreeContainer']/div/ul/li/ul/li/a/div")); + builder.MoveToElement(contentNode).ContextClick().Build().Perform(); + Thread.Sleep(1000); + + var createButton = Driver.FindElement(By.XPath("//*[@id = 'jstree-contextmenu']/li[1]/a/span/div[2]")); + createButton.Click(); + Thread.Sleep(500); + + var umbracoModalBoxIframe = Driver.FindElement(By.CssSelector(".umbModalBoxIframe")); + Driver.SwitchTo().Frame(umbracoModalBoxIframe); + + var createTextBox = Driver.FindElement(By.XPath("//input[@type='text'][1]")); + createTextBox.Clear(); + createTextBox.SendKeys("Test Page"); + + var submitButton = Driver.FindElement(By.XPath("//input[@type='submit'][1]")); + submitButton.Click(); + Thread.Sleep(2000); + + Driver.SwitchTo().Frame(rightFrame); + var saveAndPublishButton = Driver.FindElement(By.XPath("//*[@id='body_TabView1_tab01layer_publish']")); + saveAndPublishButton.Click(); + Thread.Sleep(2000); + + var contentArea = Driver.FindElement(By.XPath("//*[@id='body_TabView1']")); + Assert.IsNotNull(contentArea); + Thread.Sleep(500); + + // Perform delete + Driver.SwitchTo().DefaultContent(); + var installingModulesNode = Driver.FindElement(By.XPath("//*[@id='1052']/a/div")); + builder.MoveToElement(installingModulesNode).ContextClick().Build().Perform(); + Thread.Sleep(1000); + + var deleteButton = Driver.FindElement(By.CssSelector(".sprDelete")); + deleteButton.Click(); + var alert = Driver.SwitchTo().Alert(); + alert.Accept(); + Thread.Sleep(1000); + + // Perform move + var goFurtherNode = Driver.FindElement(By.XPath("//*[@id='1053']/a/div")); + builder.MoveToElement(goFurtherNode).ContextClick().Build().Perform(); + Thread.Sleep(1000); + + var moveButton = Driver.FindElement(By.CssSelector(".sprMove")); + moveButton.Click(); + Thread.Sleep(2000); + + umbracoModalBoxIframe = Driver.FindElement(By.CssSelector(".umbModalBoxIframe")); + Driver.SwitchTo().Frame(umbracoModalBoxIframe); + + var rootNode = Driver.FindElement(By.XPath("//*[@id='1051']")); + builder.MoveToElement(rootNode).DoubleClick().Build().Perform(); + Thread.Sleep(500); + var gettinStartedNode = Driver.FindElement(By.XPath("//*[@id='1055']/a/div")); + builder.MoveToElement(gettinStartedNode).Click().Build().Perform(); + Thread.Sleep(500); + submitButton = Driver.FindElement(By.XPath("//input[@type='submit'][1]")); + builder.MoveToElement(submitButton).Click().Build().Perform(); + Thread.Sleep(2000); + var closeLink = Driver.FindElement(By.XPath("/html/body/form/div[2]/p[2]/a")); + builder.MoveToElement(closeLink).Click().Build().Perform(); + + Driver.SwitchTo().DefaultContent(); + Thread.Sleep(1000); + + // Perform copy + var gettingStartedNode = Driver.FindElement(By.XPath("//*[@id='1054']/a/div")); + builder.MoveToElement(gettingStartedNode).ContextClick().Build().Perform(); + Thread.Sleep(1000); + + var copyButton = Driver.FindElement(By.CssSelector(".sprCopy")); + copyButton.Click(); + Thread.Sleep(2000); + + umbracoModalBoxIframe = Driver.FindElement(By.CssSelector(".umbModalBoxIframe")); + Driver.SwitchTo().Frame(umbracoModalBoxIframe); + + rootNode = Driver.FindElement(By.XPath("//*[@id='1051']")); + builder.MoveToElement(rootNode).DoubleClick().Build().Perform(); + Thread.Sleep(500); + + submitButton = Driver.FindElement(By.XPath("//input[@type='submit'][1]")); + builder.MoveToElement(submitButton).Click().Build().Perform(); + Thread.Sleep(2000); + closeLink = Driver.FindElement(By.XPath("/html/body/form/div[2]/p[2]/a")); + builder.MoveToElement(closeLink).Click().Build().Perform(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Integration/InstallPackage.cs b/src/Umbraco.Tests/Integration/InstallPackage.cs new file mode 100644 index 0000000000..2a98ac2fb8 --- /dev/null +++ b/src/Umbraco.Tests/Integration/InstallPackage.cs @@ -0,0 +1,145 @@ +using System.IO; +using System.Linq; +using System.Threading; +using NUnit.Framework; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; +using Umbraco.Core; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Integration +{ + [Ignore("We don't want to run Selenium tests on TeamCity")] + [TestFixture] + public class InstallPackage : BaseSeleniumTest + { + [SetUp] + public override void Initialize() + { + base.Initialize(); + } + + [TearDown] + public void TearDown() + { + base.TearDown(); + } + + [Test] + public void Install_Courier_Package() + { + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/login.aspx?redir="); + Driver.FindElement(By.Id("lname")).Clear(); + Driver.FindElement(By.Id("lname")).SendKeys("admin"); + Driver.FindElement(By.Id("passw")).Clear(); + Driver.FindElement(By.Id("passw")).SendKeys("test"); + Driver.FindElement(By.Id("Button1")).Click(); + Thread.Sleep(1000); + + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/umbraco.aspx#developer"); + Thread.Sleep(2000); + + var builder = new Actions(Driver); + var packagesNode = Driver.FindElement(By.XPath("//*[@id='init'][3]")); + builder.MoveToElement(packagesNode).DoubleClick().Build().Perform(); + Thread.Sleep(1000); + + var installPackageNode = Driver.FindElement(By.XPath("/html/body/div[2]/div/div/div[2]/div/div/div/div/ul/li/ul/li[3]/ul/li[4]/a/div")); + builder.MoveToElement(installPackageNode).Click().Build().Perform(); + Thread.Sleep(1000); + + var rightFrame = Driver.FindElement(By.XPath("//*[@id='right']")); + Driver.SwitchTo().Frame(rightFrame); + + const string packagesDir = @"C:\\Downloads\\Packages\\"; + var file = new DirectoryInfo(packagesDir).GetFiles().First(f => f.Name.ToLowerInvariant().StartsWith("Courier".ToLowerInvariant())); + + Driver.FindElement(By.Id("cb")).Click(); + Driver.FindElement(By.XPath("//input[@type='file']")).SendKeys(file.FullName); + Driver.FindElement(By.Id("body_ButtonLoadPackage")).Click(); + Driver.FindElement(By.Id("body_acceptCheckbox")).Click(); + Driver.FindElement(By.Id("body_ButtonInstall")).Click(); + Thread.Sleep(1000); + + var successPanel = Driver.FindElement(By.XPath("//*[@id='body_Panel1_content']")); + Assert.IsNotNull(successPanel); + } + + [Test] + public void Install_Contour_Package() + { + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/login.aspx?redir="); + Driver.FindElement(By.Id("lname")).Clear(); + Driver.FindElement(By.Id("lname")).SendKeys("admin"); + Driver.FindElement(By.Id("passw")).Clear(); + Driver.FindElement(By.Id("passw")).SendKeys("test"); + Driver.FindElement(By.Id("Button1")).Click(); + Thread.Sleep(1000); + + Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/umbraco.aspx#developer"); + Thread.Sleep(2000); + + var builder = new Actions(Driver); + var packagesNode = Driver.FindElement(By.XPath("//*[@id='init'][3]")); + builder.MoveToElement(packagesNode).DoubleClick().Build().Perform(); + Thread.Sleep(1000); + + var installPackageNode = Driver.FindElement(By.XPath("/html/body/div[2]/div/div/div[2]/div/div/div/div/ul/li/ul/li[3]/ul/li[4]/a/div")); + builder.MoveToElement(installPackageNode).Click().Build().Perform(); + Thread.Sleep(1000); + + var rightFrame = Driver.FindElement(By.XPath("//*[@id='right']")); + Driver.SwitchTo().Frame(rightFrame); + + const string packagesDir = @"C:\\Downloads\\Packages\\"; + var file = new DirectoryInfo(packagesDir).GetFiles().First(f => f.Name.ToLowerInvariant().StartsWith("UmbracoContour".ToLowerInvariant())); + + Driver.FindElement(By.Id("cb")).Click(); + Driver.FindElement(By.Id("body_file1")).SendKeys(file.Name); + Driver.FindElement(By.Id("body_ButtonLoadPackage")).Click(); + Driver.FindElement(By.Id("body_acceptCheckbox")).Click(); + Driver.FindElement(By.Id("body_ButtonInstall")).Click(); + Thread.Sleep(1000); + + var successPanel = Driver.FindElement(By.XPath("//*[@id='body_Panel1_content']")); + Assert.IsNotNull(successPanel); + } + + //[Test] + //public void Install_CMS_Import_Package() + //{ + // Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/login.aspx?redir="); + // Driver.FindElement(By.Id("lname")).Clear(); + // Driver.FindElement(By.Id("lname")).SendKeys("admin"); + // Driver.FindElement(By.Id("passw")).Clear(); + // Driver.FindElement(By.Id("passw")).SendKeys("test"); + // Driver.FindElement(By.Id("Button1")).Click(); + // Thread.Sleep(1000); + + // Driver.Navigate().GoToUrl(BaseUrl + "/umbraco/umbraco.aspx#developer"); + // Thread.Sleep(2000); + + // var builder = new Actions(Driver); + // var packagesNode = Driver.FindElement(By.XPath("//*[@id='init'][3]")); + // builder.MoveToElement(packagesNode).DoubleClick().Build().Perform(); + // Thread.Sleep(1000); + + // var installPackageNode = Driver.FindElement(By.XPath("/html/body/div[2]/div/div/div[2]/div/div/div/div/ul/li/ul/li[3]/ul/li[4]/a/div")); + // builder.MoveToElement(installPackageNode).Click().Build().Perform(); + // Thread.Sleep(1000); + + // var rightFrame = Driver.FindElement(By.XPath("//*[@id='right']")); + // Driver.SwitchTo().Frame(rightFrame); + + // Driver.FindElement(By.Id("cb")).Click(); + // Driver.FindElement(By.Id("body_file1")).SendKeys("C:\\Downloads\\Packages\\CMSImport-2.3.1.zip"); + // Driver.FindElement(By.Id("body_ButtonLoadPackage")).Click(); + // Driver.FindElement(By.Id("body_acceptCheckbox")).Click(); + // Driver.FindElement(By.Id("body_ButtonInstall")).Click(); + // Thread.Sleep(1000); + + // var successPanel = Driver.FindElement(By.XPath("//*[@id='body_Panel1_content']")); + // Assert.IsNotNull(successPanel); + //} + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs b/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs new file mode 100644 index 0000000000..832dde1e70 --- /dev/null +++ b/src/Umbraco.Tests/TestHelpers/BaseSeleniumTest.cs @@ -0,0 +1,151 @@ +using System; +using System.Data.SqlServerCe; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Linq.Dynamic; +using System.Runtime.InteropServices; +using System.Text; +using System.Web.Management; +using NUnit.Framework; +using OpenQA.Selenium; +using OpenQA.Selenium.Firefox; +using Umbraco.Core; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Migrations.Initial; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Tests.TestHelpers +{ + public class BaseSeleniumTest + { + internal IWebDriver Driver; + internal string BaseUrl; + + private StringBuilder _verificationErrors; + private UmbracoDatabase _database; + + protected ApplicationContext ApplicationContext + { + get { return ApplicationContext.Current; } + } + + [SetUp] + public virtual void Initialize() + { + + // Disable medium trust + var transform = TransformWebConfig("Release"); + + var assemblyPath = TestHelper.CurrentAssemblyDirectory; + assemblyPath = Path.Combine(assemblyPath, @"..\..\..\Umbraco.Web.UI\"); + var webUiPath = Path.GetFullPath(new Uri(assemblyPath).LocalPath); + + var installedPackagesConfig = string.Format("{0}App_Data\\packages\\installed\\installedPackages.config", webUiPath); + if (File.Exists(installedPackagesConfig)) + File.Delete(installedPackagesConfig); + + var databaseDataPath = string.Format(@"{0}\App_Data\Umbraco.sdf", webUiPath); + var connectionString = string.Format(@"Data Source={0}", databaseDataPath); + + //Create the Sql CE database + var engine = new SqlCeEngine(connectionString); + if (File.Exists(databaseDataPath) == false) + engine.CreateDatabase(); + + SqlSyntaxContext.SqlSyntaxProvider = new SqlCeSyntaxProvider(); + + _database = new UmbracoDatabase(connectionString, "System.Data.SqlServerCe.4.0"); + + // First remove anything in the database + var creation = new DatabaseSchemaCreation(_database); + creation.UninstallDatabaseSchema(); + + // Then populate it with fresh data + _database.CreateDatabaseSchema(false); + + _database.Execute("UPDATE umbracoUser SET userName = 'admin', userPassword = 'W477AMlLwwJQeAGlPZKiEILr8TA=', userEmail = 'none' WHERE id = 0"); // password: test + + // Recycle app pool so the new user can log in + //var webConfigFilePath = string.Format(@"{0}\web.config", webUiPath); + //File.SetLastWriteTime(webConfigFilePath, DateTime.Now); + + // Disable medium trust + transform = TransformWebConfig("Release"); + + Driver = new FirefoxDriver(); + BaseUrl = "http://localhost:61639/"; + _verificationErrors = new StringBuilder(); + } + + [TearDown] + public virtual void TearDown() + { + try + { + Driver.Quit(); + } + catch (Exception) + { + // Ignore errors if unable to close the browser + } + + // Re-enable medium trust + var transform = TransformWebConfig("Debug"); + + Assert.AreEqual("", _verificationErrors.ToString()); + } + + private static string TransformWebConfig(string configurationToUse) + { + var assemblyPath = TestHelper.CurrentAssemblyDirectory; + var toolsPath = Path.Combine(assemblyPath, @"..\..\..\..\tools\ConfigTransformTool\"); + var webUiPath = Path.GetFullPath(new Uri(Path.Combine(assemblyPath, @"..\..\..\Umbraco.Web.UI\")).LocalPath); + + var fileToTransform = webUiPath + "web.config"; + var transformFile = string.Format("{0}web.Template.{1}.config", webUiPath, configurationToUse); + + var psi = new ProcessStartInfo(string.Format("{0}ctt.exe", toolsPath), string.Format("s:\"{0}\" t:\"{1}\" d:\"{2}\" pw v", fileToTransform, transformFile, fileToTransform)) + { + WorkingDirectory = Environment.CurrentDirectory, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + }; + + string[] result = {string.Empty}; + using (var process = new Process { StartInfo = psi }) + { + // delegate for writing the process output to the response output + Action dataReceived = ((sender, e) => + { + if (e.Data != null) // sometimes a random event is received with null data, not sure why - I prefer to leave it out + { + result[0] += e.Data; + result[0] += "\r\n"; + } + }); + + process.OutputDataReceived += new DataReceivedEventHandler(dataReceived); + process.ErrorDataReceived += new DataReceivedEventHandler(dataReceived); + + // start the process and start reading the standard and error outputs + process.Start(); + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + + // wait for the process to exit + process.WaitForExit(); + + // an exit code other than 0 generally means an error + if (process.ExitCode != 0) + { + result[0] = result[0] + "\r\n - Exited with exitcode " + process.ExitCode; + } + } + + return result[0]; + } + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 150f3f78f2..25a2cc9bed 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -86,6 +86,7 @@ True ..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll + @@ -121,6 +122,9 @@ False ..\packages\UmbracoExamine.0.1.42.2941\lib\UmbracoExamine.dll + + ..\packages\Selenium.WebDriver.2.32.0\lib\net40\WebDriver.dll + @@ -160,6 +164,9 @@ + + + @@ -436,6 +443,7 @@ + xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /D diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config index 615a16cf25..de5e0578aa 100644 --- a/src/Umbraco.Tests/packages.config +++ b/src/Umbraco.Tests/packages.config @@ -9,6 +9,7 @@ + diff --git a/src/packages/repositories.config b/src/packages/repositories.config index f811520cac..6ee58aadf0 100644 --- a/src/packages/repositories.config +++ b/src/packages/repositories.config @@ -9,6 +9,7 @@ + diff --git a/tools/ConfigTransformTool/ctt.exe b/tools/ConfigTransformTool/ctt.exe new file mode 100644 index 0000000000..e6089d27ac Binary files /dev/null and b/tools/ConfigTransformTool/ctt.exe differ diff --git a/tools/ConfigTransformTool/readme.txt b/tools/ConfigTransformTool/readme.txt new file mode 100644 index 0000000000..e2a721689b --- /dev/null +++ b/tools/ConfigTransformTool/readme.txt @@ -0,0 +1,2 @@ +More information at: +https://ctt.codeplex.com/documentation \ No newline at end of file