using System.Diagnostics;
using umbraco.cms.businesslogic.web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic;
using System.Collections.Generic;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using System.Linq;
using System.Threading;
using umbraco.cms.businesslogic.datatype;
using umbraco.editorControls.textfield;
using umbraco.cms.businesslogic.propertytype;
using umbraco.cms.businesslogic.property;
using umbraco.cms.businesslogic.language;
using umbraco.BusinessLogic.console;
namespace umbraco.Test
{
///
/// Test for the Document API.
///
///
/// All of these tests are run in the ASP.Net context and these tests will require that there is data
/// in the Umbraco instance being tested including both document types and content.
///
/// This WILL make alot of SQL calls.
///
/// All of these tests will also delete any data that they create
///
[TestClass()]
public class DocumentTest
{
///
/// Creates a bunch of nodes in a heirarchy, then deletes the top most node (moves to the recycle bin
/// and completely deletes from system.) This should completely delete all of these nodes from the database.
///
[TestMethod()]
public void Document_Delete_Heirarchy_Permanently()
{
var docList = new List();
var total = 20;
var dt = new DocumentType(GetExistingDocTypeId());
//allow the doc type to be created underneath itself
dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
dt.Save();
//create 20 content nodes underneath each other, this will test deleting with heirarchy as well
var lastParentId = -1;
for (var i = 0; i < total; i++)
{
var newDoc = Document.MakeNew(i.ToString() + Guid.NewGuid().ToString("N"), dt, m_User, lastParentId);
docList.Add(newDoc);
Assert.IsTrue(docList[docList.Count - 1].Id > 0);
lastParentId = newDoc.Id;
}
//now delete all of them permanently, since they are nested, we only need to delete one
docList.First().delete(true);
//make sure they are all gone
foreach (var d in docList)
{
Assert.IsFalse(Document.IsNode(d.Id));
}
}
///
///A test for PublishWithResult
///
[TestMethod()]
public void Document_Publish_With_Result()
{
var val = m_NewRootDoc.PublishWithResult(m_User);
}
///
/// Creates a doc type, assigns a domain to it and removes it
///
[TestMethod()]
public void Document_Assign_Domain()
{
var d = CreateNewUnderRoot(GetExistingDocType());
var languages = Language.getAll.ToList();
Assert.IsTrue(languages.Count > 0);
//get all assigned domains
var domains = Domain.GetDomains();
var domainName = "www." + Guid.NewGuid().ToString("N") + ".com";
//add a domain name to the node with the first language found
Domain.MakeNew(domainName, d.Id, languages[0].id);
Assert.IsTrue(Domain.Exists(domainName));
Assert.AreEqual(domains.Count + 1, Domain.GetDomains().Count);
//delete the document, ensure that the domain is gone
RecycleAndDelete(d);
Assert.IsFalse(Domain.Exists(domainName));
Assert.AreEqual(domains.Count, Domain.GetDomains().Count);
}
///
///A test for making a new document and deleting it which actuall first moves it to the recycle bin
///and then deletes it.
///
[TestMethod()]
public void Document_Make_New()
{
Assert.IsInstanceOfType(m_NewRootDoc, typeof(Document));
}
///
/// A test for Copying a node, then deleting the copied node.
/// This does error checking on the case of when a node is being copied that is in the root and doesn't have a parent node, it will
/// lookup the root docs to do the test.
///
[TestMethod()]
public void Document_Copy()
{
//System.Diagnostics.Debugger.Break();
Document target = new Document(GetExistingNodeId());
int parentId = target.ParentId;
bool RelateToOrignal = false;
//get children ids for the current parent
var childrenIds = GetChildNodesOfParent(target).Select(x => x.Id);
//copy the node
target.Copy(parentId, m_User, RelateToOrignal);
//test that the child id count + 1 is equal to the total child count
Assert.AreEqual(childrenIds.Count() + 1, GetChildNodesOfParent(target).Count(), "Child node counts do not match");
//get the list of new child ids from the parent
var newChildIds = GetChildNodesOfParent(target).Select(x => x.Id);
//get the children difference which should be the new node
var diff = newChildIds.Except(childrenIds);
Assert.AreEqual(1, diff.Count());
//get the node that is the difference to compare
Document newDoc = new Document(diff.First());
Assert.AreEqual(parentId, newDoc.ParentId);
RecycleAndDelete(newDoc);
}
///
/// Tests copying by relating nodes, then deleting
///
[TestMethod()]
public void Document_Copy_And_Relate()
{
//System.Diagnostics.Debugger.Break();
Document target = new Document(GetExistingNodeId());
int parentId = target.ParentId;
bool RelateToOrignal = true;
//get children ids
var childrenIds = GetChildNodesOfParent(target).Select(x => x.Id);
target.Copy(parentId, m_User, RelateToOrignal);
var parentChildNodes = GetChildNodesOfParent(target);
Assert.AreEqual(childrenIds.Count() + 1, parentChildNodes.Count());
//get the children difference which should be the new node
var diff = parentChildNodes.Select(x => x.Id).Except(childrenIds);
Assert.AreEqual(1, diff.Count());
Document newDoc = new Document(diff.First());
RecycleAndDelete(newDoc);
}
///
///Create a new document, create preview xml for it, then delete it
///
[TestMethod()]
public void Document_To_Preview_Xml()
{
//System.Diagnostics.Debugger.Break();
var doc = m_NewRootDoc;
var id = doc.Id;
Assert.IsTrue(doc.Id > 0);
XmlDocument xd = new XmlDocument();
var xmlNode = doc.ToPreviewXml(xd);
//check the preview exists
Assert.IsTrue(doc.PreviewExists(doc.Version));
Assert.IsNotNull(xmlNode);
Assert.IsTrue(xmlNode.HasChildNodes);
}
///
/// Run test to create a node, publish it and delete it. This will test the versioning too.
///
[TestMethod()]
public void Document_Make_New_And_Publish()
{
//System.Diagnostics.Debugger.Break();
var doc = m_NewRootDoc;
var id = doc.Id;
Assert.IsTrue(doc.Id > 0);
var versionCount = doc.GetVersions().Count();
doc.Publish(m_User);
Assert.IsTrue(doc.Published);
Assert.AreEqual(versionCount + 1, doc.GetVersions().Count());
}
///
///A test that creates a new document, publishes it, unpublishes it and finally deletes it
///
[TestMethod()]
public void Document_Publish_Then_UnPublish()
{
//System.Diagnostics.Debugger.Break();
var doc = m_NewRootDoc;
var id = doc.Id;
Assert.IsTrue(doc.Id > 0);
var versionCount = doc.GetVersions().Count();
doc.Publish(m_User);
Assert.IsTrue(doc.Published);
Assert.AreEqual(versionCount + 1, doc.GetVersions().Count());
doc.UnPublish();
Assert.IsFalse(doc.Published);
}
///
///A test that makes a new document, updates some properties, saves and publishes the document, then rolls the document back and finally deletes it.
///
[TestMethod()]
public void Document_Save_And_Publish_Then_Roll_Back()
{
//System.Diagnostics.Debugger.Break();
//create new document in the root
var doc = m_NewRootDoc;
var id = doc.Id;
Assert.IsTrue(doc.Id > 0);
//get a text property
var prop = GetTextFieldProperty(m_ExistingDocType, doc);
var originalPropVal = prop.Value;
var versionCount = doc.GetVersions().Count();
//save
//wait a sec so that there's a time delay between the update time and version time
Thread.Sleep(1000);
doc.Save();
Assert.IsTrue(doc.HasPendingChanges());
//publish and create new version
doc.Publish(m_User);
Assert.IsTrue(doc.Published);
var versions = doc.GetVersions().ToList();
Assert.AreEqual(versionCount + 1, versions.Count());
string propertyTypeAlias = prop.PropertyType.Alias;
prop.Value = "updated!"; //udpate the prop
Assert.AreNotEqual(originalPropVal, prop.Value);
//rollback to first version
doc.RollBack(versions.OrderBy(x => x.Date).Last().Version, m_User);
var rolledBack = new Document(id);
Assert.AreEqual(originalPropVal, rolledBack.GenericProperties.ToList().Where(x => x.PropertyType.Alias == propertyTypeAlias).First().Value);
}
///
///Tests creating a new document type, then creating a new node with that document type, adding some data to it, then deleting the
///document type which should delete all documents associated with that.
///This will create a document type that has it's own id allowed as children. When we create the content nodes, we'll create
///them as children of each other to ensure the deletion occurs correctly.
///
[TestMethod()]
public void Document_Delete_All_Docs_By_Document_Type()
{
//System.Diagnostics.Debugger.Break();
//create a new doc type
string name = "TEST-" + Guid.NewGuid().ToString("N");
var dt = DocumentType.MakeNew(m_User, name);
//test the doc type
Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date);
Assert.IsTrue(dt.Id > 0);
//allow itself to be created under itself
dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
//create a tab
dt.AddVirtualTab("TEST");
//test the tab
var tabs = dt.getVirtualTabs.ToList();
Assert.AreEqual(1, tabs.Count);
//create a property
var allDataTypes = DataTypeDefinition.GetAll().ToList(); //get all definitions
dt.AddPropertyType(allDataTypes[0], "testProperty", "Test Property"); //add a property type of the first type found in the list
//test the prop
var prop = dt.getPropertyType("testProperty");
Assert.AreEqual("Test Property", prop.Name);
//create 1st node
var node1 = Document.MakeNew("TEST-" + Guid.NewGuid().ToString("N"), dt, m_User, -1);
Assert.IsTrue(node1.Id > 0);
//create 2nd node underneath node 1
var node2 = Document.MakeNew("TEST-" + Guid.NewGuid().ToString("N"), dt, m_User, node1.Id);
Assert.IsTrue(node2.Id > 0);
Assert.AreEqual(node1.Id, node2.Parent.Id);
//create 3rd node underneath node 2
var node3 = Document.MakeNew("TEST-" + Guid.NewGuid().ToString("N"), dt, m_User, node2.Id);
Assert.IsTrue(node3.Id > 0);
Assert.AreEqual(node2.Id, node3.Parent.Id);
Document.DeleteFromType(dt);
Assert.IsFalse(Document.IsNode(node1.Id));
Assert.IsFalse(Document.IsNode(node2.Id));
Assert.IsFalse(Document.IsNode(node3.Id));
//now remove the document type created
dt.delete();
Assert.IsFalse(DocumentType.IsNode(dt.Id));
}
///
/// This will find a document type that supports a heirarchy, create 2 root nodes, then create a child node under the first one,
/// then move it to the second one and finally delete everything that was created.
///
[TestMethod]
public void Document_Move()
{
//first need to document type that allows other types of document types to exist underneath it
DocumentType parent = null;
DocumentType child = null;
var ids = DocumentType.getAllUniqueNodeIdsFromObjectType(DocumentType._objectType);
foreach (var id in ids)
{
var dt = new DocumentType(id);
var allowed = dt.AllowedChildContentTypeIDs.ToList();
if (allowed.Count() > 0)
{
parent = dt;
child = new DocumentType(allowed[0]);
break;
}
}
if (parent == null || child == null)
{
throw new NotImplementedException("The umbraco install doesn't have document types that support a heirarchy");
}
//now that we have a parent and a child, we need to create some documents
var node1 = Document.MakeNew("FromCopy" + Guid.NewGuid().ToString("N"), parent, m_User, -1);
Assert.IsTrue(node1.Id > 0);
var node2 = Document.MakeNew("ToCopy" + Guid.NewGuid().ToString("N"), parent, m_User, -1);
Assert.IsTrue(node2.Id > 0);
//we now have 2 nodes in the root of the same type, we'll create a child node under node1 and move it to node2
var childNode = Document.MakeNew("ChildCopy" + Guid.NewGuid().ToString("N"), child, m_User, node2.Id);
Assert.IsTrue(childNode.Id > 0);
childNode.Move(node2.Id);
Assert.AreEqual(node2.Id, childNode.Parent.Id);
RecycleAndDelete(childNode);
RecycleAndDelete(node2);
RecycleAndDelete(node1);
}
///
/// This will find an existing node, copy it to the same parent, delete the copied node and restore it, then finally completley remove it.
///
[TestMethod]
public void Document_Undelete()
{
//find existing content
var doc = new Document(GetExistingNodeId());
//create new content based on the existing content in the same heirarchy
var dt = new DocumentType(doc.ContentType.Id);
var parentId = doc.ParentId;
var newDoc = Document.MakeNew("NewDoc" + Guid.NewGuid().ToString("N"), dt, m_User, parentId);
Assert.IsTrue(newDoc.Id > 0);
//this will recycle the node
newDoc.delete();
Assert.IsTrue(newDoc.IsTrashed);
Assert.IsTrue(newDoc.Path.Contains("," + (int)RecycleBin.RecycleBinType.Content + ","));
//undelete the node (move it)
newDoc.Move(parentId);
Assert.IsFalse(newDoc.IsTrashed);
Assert.IsFalse(newDoc.Path.Contains("," + (int)RecycleBin.RecycleBinType.Content + ","));
//remove it completely
RecycleAndDelete(newDoc);
}
///
/// This method will create 20 content nodes, send them to the recycle bin and then empty the recycle bin
///
[TestMethod]
public void Document_Empty_Recycle_Bin()
{
var docList = new List();
var total = 20;
var dt = m_ExistingDocType;
//allow the doc type to be created underneath itself
dt.AllowedChildContentTypeIDs = new int[] { dt.Id };
dt.Save();
//create 20 content nodes underneath each other, this will test deleting with heirarchy as well
var lastParentId = -1;
for (var i = 0; i < total; i++)
{
var newDoc = Document.MakeNew("R-" + i.ToString() + Guid.NewGuid().ToString("N"), dt, m_User, lastParentId);
docList.Add(newDoc);
Assert.IsTrue(docList[docList.Count - 1].Id > 0);
Assert.AreEqual(lastParentId, newDoc.ParentId);
lastParentId = newDoc.Id;
}
//now delete all of them, since they are nested, we only need to delete one
docList.First().delete();
//a callback action for each item removed from the recycle bin
var totalDeleted = 0;
var bin = new RecycleBin(RecycleBin.RecycleBinType.Content);
var totalTrashedItems = bin.GetDescendants().Cast