diff --git a/.gitignore b/.gitignore
index b06e864a3..adb95558a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -197,6 +197,9 @@ UpgradeLog*.htm
# Microsoft Fakes
FakesAssemblies/
+# App.Config files
+[Aa]pp.[Cc]onfig
+
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
diff --git a/OfficeDevPnP.PowerShell.sln b/OfficeDevPnP.PowerShell.sln
index c426ab1a2..da6fc68f3 100644
--- a/OfficeDevPnP.PowerShell.sln
+++ b/OfficeDevPnP.PowerShell.sln
@@ -23,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentat
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "OfficeDevPnP.PowerShell.Setup", "Setup\OfficeDevPnP.PowerShell.Setup.wixproj", "{17C05F96-5D99-4367-AB05-7C07D2570F08}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OfficeDevPnP.PowerShell.Tests", "Tests\OfficeDevPnP.PowerShell.Tests.csproj", "{AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -118,6 +120,30 @@ Global
{17C05F96-5D99-4367-AB05-7C07D2570F08}.Release15|Mixed Platforms.Build.0 = Release|x86
{17C05F96-5D99-4367-AB05-7C07D2570F08}.Release15|x86.ActiveCfg = Release|x86
{17C05F96-5D99-4367-AB05-7C07D2570F08}.Release15|x86.Build.0 = Release|x86
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug|x86.Build.0 = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug15|Any CPU.ActiveCfg = Debug15|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug15|Any CPU.Build.0 = Debug15|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug15|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug15|Mixed Platforms.Build.0 = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug15|x86.ActiveCfg = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Debug15|x86.Build.0 = Debug|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release|x86.ActiveCfg = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release|x86.Build.0 = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release15|Any CPU.ActiveCfg = Release15|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release15|Any CPU.Build.0 = Release15|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release15|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release15|Mixed Platforms.Build.0 = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release15|x86.ActiveCfg = Release|Any CPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}.Release15|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Tests/AdminTests.cs b/Tests/AdminTests.cs
new file mode 100644
index 000000000..53a318865
--- /dev/null
+++ b/Tests/AdminTests.cs
@@ -0,0 +1,54 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Management.Automation.Runspaces;
+
+namespace OfficeDevPnP.PowerShell.Tests
+{
+ [TestClass]
+ public class GetTenantSiteTests
+ {
+ [TestMethod]
+ public void GetTenantSiteTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Get-SPOTenantSite");
+
+ Assert.IsTrue(results.Count > 0);
+ }
+ }
+
+ [TestMethod]
+ public void GetTimeZoneIdTest1()
+ {
+ using (var scope = new PSTestScope(false))
+ {
+ var results = scope.ExecuteCommand("Get-SPOTimeZoneId");
+ Assert.IsTrue(results.Count > 0);
+ }
+ }
+
+ [TestMethod]
+ public void GetTimeZoneIdTest2()
+ {
+ using (var scope = new PSTestScope(false))
+ {
+ var results = scope.ExecuteCommand("Get-SPOTimeZoneId", new CommandParameter("Match", "Stockholm"));
+
+ Assert.IsTrue(results.Count == 1);
+ }
+ }
+
+ [TestMethod]
+ public void GetWebTemplatesTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Get-SPOWebTemplates");
+
+ Assert.IsTrue(results.Count > 0);
+ Assert.IsTrue(results[0].BaseObject.GetType().Equals(typeof(Microsoft.Online.SharePoint.TenantAdministration.SPOTenantWebTemplate)));
+ }
+ }
+ }
+}
diff --git a/Tests/App.config.sample b/Tests/App.config.sample
new file mode 100644
index 000000000..5b66dfb58
--- /dev/null
+++ b/Tests/App.config.sample
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Tests/BaseTests.cs b/Tests/BaseTests.cs
new file mode 100644
index 000000000..8c83bed9b
--- /dev/null
+++ b/Tests/BaseTests.cs
@@ -0,0 +1,40 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Management.Automation.Runspaces;
+using System.Management.Automation;
+using System.Collections.ObjectModel;
+using OfficeDevPnP.PowerShell.Commands.Base;
+using OfficeDevPnP.PowerShell.Tests;
+using System.Configuration;
+
+namespace OfficeDevPnP.PowerShell.Tests
+{
+ [TestClass]
+ public class BaseTests
+ {
+ [TestMethod]
+ public void ConnectSPOnlineTest1()
+ {
+ using (var scope = new PSTestScope(false))
+ {
+ var results = scope.ExecuteCommand("Connect-SPOnline", new CommandParameter("Url", ConfigurationManager.AppSettings["SPODevSiteUrl"]));
+ Assert.IsTrue(results.Count == 0);
+ }
+ }
+
+ [TestMethod]
+ public void ConnectSPOnlineTest2()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Get-SPOContext");
+
+ Assert.IsTrue(results.Count == 1);
+ Assert.IsTrue(results[0].BaseObject.GetType() == typeof(Microsoft.SharePoint.Client.ClientContext));
+
+ }
+ }
+
+
+ }
+}
diff --git a/Tests/BrandingTests.cs b/Tests/BrandingTests.cs
new file mode 100644
index 000000000..abe161913
--- /dev/null
+++ b/Tests/BrandingTests.cs
@@ -0,0 +1,262 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Management.Automation.Runspaces;
+using Microsoft.SharePoint.Client;
+using System.Linq;
+using OfficeDevPnP.Core.Enums;
+
+namespace OfficeDevPnP.PowerShell.Tests
+{
+ [TestClass]
+ public class BrandingTests
+ {
+ [TestMethod]
+ public void AddCustomActionTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Add-SPOCustomAction",
+ new CommandParameter("Name", "TestCustomAction"),
+ new CommandParameter("Title", "TestCustomAction"),
+ new CommandParameter("Description", "Test Custom Action Description"),
+ new CommandParameter("Group", "ActionsMenu"),
+ new CommandParameter("Location", "Microsoft.SharePoint.StandardMenu")
+ );
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.LoadQuery(context.Web.UserCustomActions.Where(ca => ca.Name == "TestCustomAction"));
+ context.ExecuteQueryRetry();
+
+ Assert.IsTrue(actions.Any());
+
+ actions.FirstOrDefault().DeleteObject();
+ context.ExecuteQueryRetry();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void AddJavascriptBlockTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Add-SPOJavascriptBlock",
+ new CommandParameter("Name", "TestJavascriptBlock"),
+ new CommandParameter("Script", ""));
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.Web.GetCustomActions().Where(c => c.Location == "ScriptLink" && c.Name == "TestJavascriptBlock");
+ Assert.IsTrue(actions.Any());
+
+ actions.FirstOrDefault().DeleteObject();
+ context.ExecuteQueryRetry();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void AddJavascriptLinkTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Add-SPOJavascriptLink",
+ new CommandParameter("Key", "TestJavascriptLink"),
+ new CommandParameter("Url", "https://testserver.com/testtojavascriptlink.js"));
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.Web.GetCustomActions().Where(c => c.Location == "ScriptLink" && c.Name == "TestJavascriptLink");
+ Assert.IsTrue(actions.Any());
+
+ actions.FirstOrDefault().DeleteObject();
+ context.ExecuteQueryRetry();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void AddNavigationNodeTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Add-SPONavigationNode",
+ new CommandParameter("Location", NavigationType.QuickLaunch),
+ new CommandParameter("Title", "Test Navigation Item"),
+ new CommandParameter("Url", "https://testserver.com/testtojavascriptlink.js"));
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var nodes = context.LoadQuery(context.Web.Navigation.QuickLaunch.Where(n => n.Title == "Test Navigation Item"));
+ context.ExecuteQueryRetry();
+
+ Assert.IsTrue(nodes.Any());
+
+ nodes.FirstOrDefault().DeleteObject();
+ context.ExecuteQueryRetry();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void GetCustomActionTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ scope.ExecuteCommand("Add-SPOJavascriptLink",
+ new CommandParameter("Key", "TestJavascriptLink"),
+ new CommandParameter("Url", "https://testserver.com/testtojavascriptlink.js"));
+
+ var results = scope.ExecuteCommand("Get-SPOCustomAction");
+
+ Assert.IsTrue(results.Any());
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.Web.GetCustomActions().Where(c => c.Location == "ScriptLink" && c.Name == "TestJavascriptLink");
+
+ actions.FirstOrDefault().DeleteObject();
+ context.ExecuteQueryRetry();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void GetJavaScriptLinkTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ scope.ExecuteCommand("Add-SPOJavascriptLink",
+ new CommandParameter("Key", "TestJavascriptLink"),
+ new CommandParameter("Url", "https://testserver.com/testtojavascriptlink.js"));
+
+ var results = scope.ExecuteCommand("Get-SPOJavaScriptLink");
+
+ Assert.IsTrue(results.Any());
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.Web.GetCustomActions().Where(c => c.Location == "ScriptLink" && c.Name == "TestJavascriptLink");
+
+ actions.FirstOrDefault().DeleteObject();
+ context.ExecuteQueryRetry();
+ }
+ }
+ }
+
+ [TestMethod]
+ [Ignore]
+ public void GetProvisioningTemplateTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Get-SPOProvisioningTemplate");
+
+ Assert.IsTrue(results.Any());
+
+ Assert.IsTrue(results.FirstOrDefault().BaseObject.GetType() == typeof(string));
+ }
+ }
+
+ [TestMethod]
+ public void RemoveCustomActionTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ scope.ExecuteCommand("Add-SPOCustomAction",
+ new CommandParameter("Name", "TestCustomAction"),
+ new CommandParameter("Title", "TestCustomAction"),
+ new CommandParameter("Description", "Test Custom Action Description"),
+ new CommandParameter("Group", "ActionsMenu"),
+ new CommandParameter("Location", "Microsoft.SharePoint.StandardMenu")
+ );
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.LoadQuery(context.Web.UserCustomActions.Where(ca => ca.Name == "TestCustomAction"));
+ context.ExecuteQueryRetry();
+
+ Assert.IsTrue(actions.Any());
+
+ var id = actions.FirstOrDefault().Id;
+
+ scope.ExecuteCommand("Remove-SPOCustomAction",
+ new CommandParameter("Identity", id),
+ new CommandParameter("Force", true));
+
+ actions = context.LoadQuery(context.Web.UserCustomActions.Where(ca => ca.Name == "TestCustomAction"));
+ context.ExecuteQueryRetry();
+
+ Assert.IsFalse(actions.Any());
+ }
+ }
+ }
+
+ [TestMethod]
+ public void RemoveJavascriptLinkTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Add-SPOJavascriptLink",
+ new CommandParameter("Key", "TestJavascriptLink"),
+ new CommandParameter("Url", "https://testserver.com/testtojavascriptlink.js"));
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var actions = context.Web.GetCustomActions().Where(c => c.Location == "ScriptLink" && c.Name == "TestJavascriptLink");
+ Assert.IsTrue(actions.Any());
+
+ var name = actions.FirstOrDefault().Name;
+
+ scope.ExecuteCommand("Remove-SPOJavaScriptLink",
+ new CommandParameter("Name", name),
+ new CommandParameter("Force", true));
+
+ actions = context.Web.GetCustomActions().Where(c => c.Location == "ScriptLink" && c.Name == "TestJavascriptLink");
+ Assert.IsFalse(actions.Any());
+
+ }
+ }
+ }
+
+ [TestMethod]
+ public void RemoveNavigationNodeTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Add-SPONavigationNode",
+ new CommandParameter("Location", NavigationType.QuickLaunch),
+ new CommandParameter("Title", "Test Navigation Item"),
+ new CommandParameter("Url", "https://testserver.com/testtojavascriptlink.js"));
+
+
+ using (var context = TestCommon.CreateClientContext())
+ {
+ var nodes = context.LoadQuery(context.Web.Navigation.QuickLaunch.Where(n => n.Title == "Test Navigation Item"));
+ context.ExecuteQueryRetry();
+
+ Assert.IsTrue(nodes.Any());
+
+ scope.ExecuteCommand("Remove-SPONavigationNode",
+ new CommandParameter("Location", NavigationType.QuickLaunch),
+ new CommandParameter("Title", "Test Navigation Item"),
+ new CommandParameter("Force", true)
+ );
+
+ nodes = context.LoadQuery(context.Web.Navigation.QuickLaunch.Where(n => n.Title == "Test Navigation Item"));
+ context.ExecuteQueryRetry();
+
+ Assert.IsFalse(nodes.Any());
+ }
+ }
+ }
+ }
+}
+
diff --git a/Tests/ListsTests.cs b/Tests/ListsTests.cs
new file mode 100644
index 000000000..e255a21fe
--- /dev/null
+++ b/Tests/ListsTests.cs
@@ -0,0 +1,22 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace OfficeDevPnP.PowerShell.Tests
+{
+ [TestClass]
+ public class ListsTests
+ {
+ [TestMethod]
+ public void GetSPOListTest()
+ {
+ using (var scope = new PSTestScope(true))
+ {
+ var results = scope.ExecuteCommand("Get-SPOList", null);
+
+ Assert.IsTrue(results.Count > 0);
+ Assert.IsTrue(results[0].BaseObject.GetType() == typeof(Microsoft.SharePoint.Client.List));
+
+ }
+ }
+ }
+}
diff --git a/Tests/OfficeDevPnP.PowerShell.Tests.csproj b/Tests/OfficeDevPnP.PowerShell.Tests.csproj
new file mode 100644
index 000000000..7a497f430
--- /dev/null
+++ b/Tests/OfficeDevPnP.PowerShell.Tests.csproj
@@ -0,0 +1,241 @@
+
+
+
+ Debug
+ AnyCPU
+ {AD2E3CF9-65C7-40FD-9F52-CE8259031C6E}
+ Library
+ Properties
+ OfficeDevPnP.PowerShell.Tests
+ OfficeDevPnP.PowerShell.Tests
+ v4.5.2
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+ bin\Debug15\
+ TRACE;DEBUG;CLIENTSDKV15
+ full
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\Release15\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.Office.Client.Policy.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.Office.Client.TranslationServices.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.Online.SharePoint.Client.Tenant.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.DocumentManagement.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.Publishing.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.Runtime.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.Search.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.Search.Applications.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.Taxonomy.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.UserProfiles.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\16\Microsoft.SharePoint.Client.WorkflowServices.dll
+
+
+ False
+ ..\ReferenceAssemblies\16\Microsoft.Office.Client.Education.dll
+
+
+
+
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.Office.Client.Policy.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.Office.Client.TranslationServices.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.Online.SharePoint.Client.Tenant.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.DocumentManagement.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.Publishing.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.Runtime.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.Search.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.Search.Applications.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.Taxonomy.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.UserProfiles.dll
+
+
+ False
+ ..\..\PnP-Sites-Core\Assemblies\15\Microsoft.SharePoint.Client.WorkflowServices.dll
+
+
+ False
+ ..\ReferenceAssemblies\15\Microsoft.Office.Client.Education.dll
+
+
+
+
+
+
+ False
+ ..\..\PnP-Sites-Core\Core\OfficeDevPnP.Core\bin\$(Configuration)\OfficeDevPnP.Core.dll
+
+
+
+
+ False
+ ..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll
+
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {1dde6f0a-ca49-419a-9ce8-a6ca02f43ce0}
+ OfficeDevPnP.PowerShell.Commands
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Tests/PSTestScope.cs b/Tests/PSTestScope.cs
new file mode 100644
index 000000000..65c4ff13a
--- /dev/null
+++ b/Tests/PSTestScope.cs
@@ -0,0 +1,83 @@
+using Microsoft.PowerShell.Commands;
+using OfficeDevPnP.PowerShell.Commands.Base;
+using System;
+using System.Collections.ObjectModel;
+using System.Configuration;
+using System.Management.Automation;
+using System.Management.Automation.Runspaces;
+
+namespace OfficeDevPnP.PowerShell.Tests
+{
+ public class PSTestScope : IDisposable
+ {
+ private Runspace _runSpace;
+
+ public string SiteUrl { get; set; }
+ public string CredentialManagerEntry { get; set; }
+
+ public PSTestScope(bool connect = true)
+ {
+ SiteUrl = ConfigurationManager.AppSettings["SPODevSiteUrl"];
+ CredentialManagerEntry = ConfigurationManager.AppSettings["SPOCredentialManagerLabel"];
+
+ var iss = InitialSessionState.CreateDefault();
+ if (connect)
+ {
+ SessionStateCmdletEntry ssce = new SessionStateCmdletEntry("Connect-SPOnline", typeof(ConnectSPOnline), null);
+
+ iss.Commands.Add(ssce);
+ }
+ _runSpace = RunspaceFactory.CreateRunspace(iss);
+
+ _runSpace.Open();
+
+
+ if (connect)
+ {
+ var pipeLine = _runSpace.CreatePipeline();
+ Command cmd = new Command("connect-sponline");
+ cmd.Parameters.Add("Url", SiteUrl);
+ if (!string.IsNullOrEmpty(CredentialManagerEntry))
+ {
+ cmd.Parameters.Add("Credentials", CredentialManagerEntry);
+ }
+ pipeLine.Commands.Add(cmd);
+ pipeLine.Invoke();
+ }
+ }
+
+
+ public Collection ExecuteCommand(string cmdletString)
+ {
+ return ExecuteCommand(cmdletString, null);
+ }
+
+ public Collection ExecuteCommand(string cmdletString, params CommandParameter[] parameters)
+ {
+ var pipeLine = _runSpace.CreatePipeline();
+ Command cmd = new Command(cmdletString);
+ if (parameters != null)
+ {
+ foreach (var parameter in parameters)
+ {
+ cmd.Parameters.Add(parameter);
+ }
+ }
+ pipeLine.Commands.Add(cmd);
+ return pipeLine.Invoke();
+
+ }
+
+ public void Dispose()
+ {
+ //if (_powerShell != null)
+ //{
+ // _powerShell.Dispose();
+ //}
+ if (_runSpace != null)
+ {
+ _runSpace.Dispose();
+ }
+ }
+ }
+}
diff --git a/Tests/Properties/AssemblyInfo.cs b/Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..a056d97c6
--- /dev/null
+++ b/Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tests")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ad2e3cf9-65c7-40fd-9f52-ce8259031c6e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tests/TestCommon.cs b/Tests/TestCommon.cs
new file mode 100644
index 000000000..2e0eefae0
--- /dev/null
+++ b/Tests/TestCommon.cs
@@ -0,0 +1,140 @@
+using Microsoft.SharePoint.Client;
+using System;
+using System.Configuration;
+using System.Security;
+using System.Net;
+
+namespace OfficeDevPnP.PowerShell.Tests
+{
+ static class TestCommon
+ {
+ #region Constructor
+ static TestCommon()
+ {
+ // Read configuration data
+ TenantUrl = ConfigurationManager.AppSettings["SPOTenantUrl"];
+ DevSiteUrl = ConfigurationManager.AppSettings["SPODevSiteUrl"];
+
+ if (string.IsNullOrEmpty(TenantUrl) || string.IsNullOrEmpty(DevSiteUrl))
+ {
+ throw new ConfigurationErrorsException("Tenant credentials in App.config are not set up.");
+ }
+
+ if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["SPOCredentialManagerLabel"]))
+ {
+ Credentials = Core.Utilities.CredentialManager.GetSharePointOnlineCredential(ConfigurationManager.AppSettings["SPOCredentialManagerLabel"]);
+ }
+ else
+ {
+ if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["SPOUserName"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["SPOPassword"]))
+ {
+ UserName = ConfigurationManager.AppSettings["SPOUserName"];
+ var password = ConfigurationManager.AppSettings["SPOPassword"];
+
+ Password = GetSecureString(password);
+ Credentials = new SharePointOnlineCredentials(UserName, Password);
+ }
+ else if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["OnPremUserName"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["OnPremDomain"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["OnPremPassword"]))
+ {
+ Password = GetSecureString(ConfigurationManager.AppSettings["OnPremPassword"]);
+ Credentials = new NetworkCredential(ConfigurationManager.AppSettings["OnPremUserName"], Password, ConfigurationManager.AppSettings["OnPremDomain"]);
+ }
+ else if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["Realm"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["AppId"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["AppSecret"]))
+ {
+ Realm = ConfigurationManager.AppSettings["Realm"];
+ AppId = ConfigurationManager.AppSettings["AppId"];
+ AppSecret = ConfigurationManager.AppSettings["AppSecret"];
+ }
+ else
+ {
+ throw new ConfigurationErrorsException("Tenant credentials in App.config are not set up.");
+ }
+ }
+ }
+ #endregion
+
+ #region Properties
+ public static string TenantUrl { get; set; }
+ public static string DevSiteUrl { get; set; }
+ static string UserName { get; set; }
+ static SecureString Password { get; set; }
+ static ICredentials Credentials { get; set; }
+ static string Realm { get; set; }
+ static string AppId { get; set; }
+ static string AppSecret { get; set; }
+
+ public static String AzureStorageKey
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings["AzureStorageKey"];
+ }
+ }
+ #endregion
+
+ #region Methods
+ public static ClientContext CreateClientContext()
+ {
+ return CreateContext(DevSiteUrl, Credentials);
+ }
+
+ public static ClientContext CreateTenantClientContext()
+ {
+ return CreateContext(TenantUrl, Credentials);
+ }
+
+ public static bool AppOnlyTesting()
+ {
+ if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["Realm"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["AppId"]) &&
+ !String.IsNullOrEmpty(ConfigurationManager.AppSettings["AppSecret"]) &&
+ String.IsNullOrEmpty(ConfigurationManager.AppSettings["SPOCredentialManagerLabel"]) &&
+ String.IsNullOrEmpty(ConfigurationManager.AppSettings["SPOUserName"]) &&
+ String.IsNullOrEmpty(ConfigurationManager.AppSettings["SPOPassword"]) &&
+ String.IsNullOrEmpty(ConfigurationManager.AppSettings["OnPremUserName"]) &&
+ String.IsNullOrEmpty(ConfigurationManager.AppSettings["OnPremDomain"]) &&
+ String.IsNullOrEmpty(ConfigurationManager.AppSettings["OnPremPassword"]))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private static ClientContext CreateContext(string contextUrl, ICredentials credentials)
+ {
+ ClientContext context;
+ if (!String.IsNullOrEmpty(Realm) && !String.IsNullOrEmpty(AppId) && !String.IsNullOrEmpty(AppSecret))
+ {
+ var am = new OfficeDevPnP.Core.AuthenticationManager();
+ context = am.GetAppOnlyAuthenticatedContext(contextUrl, Realm, AppId, AppSecret);
+ }
+ else
+ {
+ context = new ClientContext(contextUrl);
+ context.Credentials = credentials;
+ }
+ return context;
+ }
+
+ private static SecureString GetSecureString(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ throw new ArgumentException("Input string is empty and cannot be made into a SecureString", "input");
+
+ var secureString = new SecureString();
+ foreach (char c in input.ToCharArray())
+ secureString.AppendChar(c);
+
+ return secureString;
+ }
+ #endregion
+ }
+}