diff --git a/src/code/Utils.cs b/src/code/Utils.cs
index 95de2075d..440a18d86 100644
--- a/src/code/Utils.cs
+++ b/src/code/Utils.cs
@@ -2,15 +2,17 @@
// Licensed under the MIT License.
using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Management.Automation;
using System.Management.Automation.Language;
namespace Microsoft.PowerShell.PowerShellGet.UtilClasses
{
- #region Utils
-
internal static class Utils
{
- #region Members
+ #region Public methods
public static string TrimQuotes(string name)
{
@@ -37,7 +39,406 @@ public static string QuoteName(string name)
return "'" + CodeGeneration.EscapeSingleQuotedStringContent(name) + "'";
}
+ ///
+ /// Converts an ArrayList of object types to a string array.
+ ///
+ public static string[] GetStringArray(ArrayList list)
+ {
+ if (list == null) { return null; }
+
+ var strArray = new string[list.Count];
+ for (int i=0; i
+ /// Constructor
+ ///
+ /// Provided hashtable has form:
+ /// Key: Cmdlet
+ /// Value: ArrayList of Cmdlet name strings
+ /// Key: Command
+ /// Value: ArrayList of Command name strings
+ /// Key: DscResource
+ /// Value: ArrayList of DscResource name strings
+ /// Key: Function
+ /// Value: ArrayList of Function name strings
+ /// Key: RoleCapability (deprecated for PSGetV3)
+ /// Value: ArrayList of RoleCapability name strings
+ /// Key: Workflow (deprecated for PSGetV3)
+ /// Value: ArrayList of Workflow name strings
+ ///
+ /// Hashtable of PSGet includes
+ public PSGetIncludes(Hashtable includes)
+ {
+ if (includes == null) { return; }
+
+ Cmdlet = GetHashTableItem(includes, nameof(Cmdlet));
+ Command = GetHashTableItem(includes, nameof(Command));
+ DscResource = GetHashTableItem(includes, nameof(DscResource));
+ Function = GetHashTableItem(includes, nameof(Function));
+ RoleCapability = GetHashTableItem(includes, nameof(RoleCapability));
+ Workflow = GetHashTableItem(includes, nameof(Workflow));
+ }
+
+ #endregion
+
+ #region Public methods
+
+ public Hashtable ConvertToHashtable()
+ {
+ var hashtable = new Hashtable
+ {
+ { nameof(Cmdlet), Cmdlet },
+ { nameof(Command), Command },
+ { nameof(DscResource), DscResource },
+ { nameof(Function), Function },
+ { nameof(RoleCapability), RoleCapability },
+ { nameof(Workflow), Workflow }
+ };
+
+ return hashtable;
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private string[] GetHashTableItem(
+ Hashtable table,
+ string name)
+ {
+ if (table.ContainsKey(name) &&
+ table[name] is PSObject psObjectItem)
+ {
+ return Utils.GetStringArray(psObjectItem.BaseObject as ArrayList);
+ }
+
+ return null;
+ }
+
+ #endregion
+ }
+
+ internal sealed class PSGetResourceInfo
+ {
+ #region Properties
+
+ public Dictionary AdditionalMetadata { get; set; }
+
+ public string Author { get; set; }
+
+ public string CompanyName { get; set; }
+
+ public string Copyright { get; set; }
+
+ public string[] Dependencies { get; set; }
+
+ public string Description { get; set; }
+
+ public Uri IconUri { get; set; }
+
+ public PSGetIncludes Includes { get; set; }
+
+ public DateTime InstalledDate { get; set; }
+
+ public string InstalledLocation { get; set; }
+
+ public Uri LicenseUri { get; set; }
+
+ public string Name { get; set; }
+
+ public string PackageManagementProvider { get; set; }
+
+ public string PowerShellGetFormatVersion { get; set; }
+
+ public Uri ProjectUri { get; set; }
+
+ public DateTime PublishedDate { get; set; }
+
+ public string ReleaseNotes { get; set; }
+
+ public string Repository { get; set; }
+
+ public string RepositorySourceLocation { get; set; }
+
+ public string[] Tags { get; set; }
+
+ public string Type { get; set; }
+
+ public DateTime UpdatedDate { get; set; }
+
+ public Version Version { get; set; }
+
+ #endregion
+
+ #region Public static methods
+
+ ///
+ /// Writes the PSGetResourceInfo properties to the specified file path as a
+ /// PowerShell serialized xml file, maintaining compatibility with
+ /// PowerShellGet v2 file format.
+ ///
+ public bool TryWrite(
+ string filePath,
+ out string errorMsg)
+ {
+ errorMsg = string.Empty;
+
+ if (string.IsNullOrWhiteSpace(filePath))
+ {
+ errorMsg = "TryWritePSGetInfo: Invalid file path. Filepath cannot be empty or whitespace.";
+ return false;
+ }
+
+ try
+ {
+ var infoXml = PSSerializer.Serialize(
+ source: ConvertToCustomObject(),
+ depth: 5);
+
+ System.IO.File.WriteAllText(
+ path: filePath,
+ contents: infoXml);
+
+ return true;
+ }
+ catch(Exception ex)
+ {
+ errorMsg = string.Format(
+ CultureInfo.InvariantCulture,
+ @"TryWritePSGetInfo: Cannot convert and write the PowerShellGet information to file, with error: {0}",
+ ex.Message);
+
+ return false;
+ }
+ }
+
+ ///
+ /// Reads a PSGet resource xml (PowerShell serialized) file and returns
+ /// a PSGetResourceInfo object containing the file contents.
+ ///
+ public static bool TryRead(
+ string filePath,
+ out PSGetResourceInfo psGetInfo,
+ out string errorMsg)
+ {
+ psGetInfo = null;
+ errorMsg = string.Empty;
+
+ if (string.IsNullOrWhiteSpace(filePath))
+ {
+ errorMsg = "TryReadPSGetInfo: Invalid file path. Filepath cannot be empty or whitespace.";
+ return false;
+ }
+
+ try
+ {
+ // Read and deserialize information xml file.
+ var psObjectInfo = (PSObject) PSSerializer.Deserialize(
+ System.IO.File.ReadAllText(
+ filePath));
+
+ psGetInfo = new PSGetResourceInfo
+ {
+ AdditionalMetadata = GetProperty>(nameof(PSGetResourceInfo.AdditionalMetadata), psObjectInfo),
+ Author = GetProperty(nameof(PSGetResourceInfo.Author), psObjectInfo),
+ CompanyName = GetProperty(nameof(PSGetResourceInfo.CompanyName), psObjectInfo),
+ Copyright = GetProperty(nameof(PSGetResourceInfo.Copyright), psObjectInfo),
+ Dependencies = Utils.GetStringArray(GetProperty(nameof(PSGetResourceInfo.Dependencies), psObjectInfo)),
+ Description = GetProperty(nameof(PSGetResourceInfo.Description), psObjectInfo),
+ IconUri = GetProperty(nameof(PSGetResourceInfo.IconUri), psObjectInfo),
+ Includes = new PSGetIncludes(GetProperty(nameof(PSGetResourceInfo.Includes), psObjectInfo)),
+ InstalledDate = GetProperty(nameof(PSGetResourceInfo.InstalledDate), psObjectInfo),
+ InstalledLocation = GetProperty(nameof(PSGetResourceInfo.InstalledLocation), psObjectInfo),
+ LicenseUri = GetProperty(nameof(PSGetResourceInfo.LicenseUri), psObjectInfo),
+ Name = GetProperty(nameof(PSGetResourceInfo.Name), psObjectInfo),
+ PackageManagementProvider = GetProperty(nameof(PSGetResourceInfo.PackageManagementProvider), psObjectInfo),
+ PowerShellGetFormatVersion = GetProperty(nameof(PSGetResourceInfo.PowerShellGetFormatVersion), psObjectInfo),
+ ProjectUri = GetProperty(nameof(PSGetResourceInfo.ProjectUri), psObjectInfo),
+ PublishedDate = GetProperty(nameof(PSGetResourceInfo.PublishedDate), psObjectInfo),
+ ReleaseNotes = GetProperty(nameof(PSGetResourceInfo.ReleaseNotes), psObjectInfo),
+ Repository = GetProperty(nameof(PSGetResourceInfo.Repository), psObjectInfo),
+ RepositorySourceLocation = GetProperty(nameof(PSGetResourceInfo.RepositorySourceLocation), psObjectInfo),
+ Tags = Utils.GetStringArray(GetProperty(nameof(PSGetResourceInfo.Tags), psObjectInfo)),
+ Type = GetProperty(nameof(PSGetResourceInfo.Type), psObjectInfo),
+ UpdatedDate = GetProperty(nameof(PSGetResourceInfo.UpdatedDate), psObjectInfo),
+ Version = GetProperty(nameof(PSGetResourceInfo.Version), psObjectInfo)
+ };
+
+ return true;
+ }
+ catch(Exception ex)
+ {
+ errorMsg = string.Format(
+ CultureInfo.InvariantCulture,
+ @"TryReadPSGetInfo: Cannot read the PowerShellGet information file with error: {0}",
+ ex.Message);
+
+ return false;
+ }
+ }
+
#endregion
+
+ #region Private static methods
+
+ private static T ConvertToType(PSObject psObject)
+ {
+ // We only convert Dictionary types.
+ if (typeof(T) != typeof(Dictionary))
+ {
+ return default(T);
+ }
+
+ var dict = new Dictionary();
+ foreach (var prop in psObject.Properties)
+ {
+ dict.Add(prop.Name, prop.Value.ToString());
+ }
+
+ return (T)Convert.ChangeType(dict, typeof(T));
+ }
+
+ private static T GetProperty(
+ string Name,
+ PSObject psObjectInfo)
+ {
+ var val = psObjectInfo.Properties[Name]?.Value;
+ if (val == null)
+ {
+ return default(T);
+ }
+
+ switch (val)
+ {
+ case T valType:
+ return valType;
+
+ case PSObject valPSObject:
+ switch (valPSObject.BaseObject)
+ {
+ case T valBase:
+ return valBase;
+
+ case PSCustomObject _:
+ // A base object of PSCustomObject means this is additional metadata
+ // and type T should be Dictionary.
+ return ConvertToType(valPSObject);
+
+ default:
+ return default(T);
+ }
+
+ default:
+ return default(T);
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private PSObject ConvertToCustomObject()
+ {
+ var additionalMetadata = new PSObject();
+ foreach (var item in AdditionalMetadata)
+ {
+ additionalMetadata.Properties.Add(new PSNoteProperty(item.Key, item.Value));
+ }
+
+ var psObject = new PSObject();
+ psObject.Properties.Add(new PSNoteProperty(nameof(AdditionalMetadata), additionalMetadata));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Author), Author));
+ psObject.Properties.Add(new PSNoteProperty(nameof(CompanyName), CompanyName));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Copyright), Copyright));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Dependencies), Dependencies));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Description), Description));
+ psObject.Properties.Add(new PSNoteProperty(nameof(IconUri), IconUri));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Includes), Includes.ConvertToHashtable()));
+ psObject.Properties.Add(new PSNoteProperty(nameof(InstalledDate), InstalledDate));
+ psObject.Properties.Add(new PSNoteProperty(nameof(InstalledLocation), InstalledLocation));
+ psObject.Properties.Add(new PSNoteProperty(nameof(LicenseUri), LicenseUri));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Name), Name));
+ psObject.Properties.Add(new PSNoteProperty(nameof(PackageManagementProvider), PackageManagementProvider));
+ psObject.Properties.Add(new PSNoteProperty(nameof(PowerShellGetFormatVersion), PowerShellGetFormatVersion));
+ psObject.Properties.Add(new PSNoteProperty(nameof(ProjectUri), ProjectUri));
+ psObject.Properties.Add(new PSNoteProperty(nameof(PublishedDate), PublishedDate));
+ psObject.Properties.Add(new PSNoteProperty(nameof(ReleaseNotes), ReleaseNotes));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Repository), Repository));
+ psObject.Properties.Add(new PSNoteProperty(nameof(RepositorySourceLocation), RepositorySourceLocation));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Tags), Tags));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Type), Type));
+ psObject.Properties.Add(new PSNoteProperty(nameof(UpdatedDate), UpdatedDate));
+ psObject.Properties.Add(new PSNoteProperty(nameof(Version), Version));
+
+ return psObject;
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ #region Test Hooks
+
+ public static class TestHooks
+ {
+ public static PSObject ReadPSGetResourceInfo(string filePath)
+ {
+ if (PSGetResourceInfo.TryRead(filePath, out PSGetResourceInfo psGetInfo, out string errorMsg))
+ {
+ return PSObject.AsPSObject(psGetInfo);
+ }
+
+ throw new PSInvalidOperationException(errorMsg);
+ }
+
+ public static void WritePSGetResourceInfo(
+ string filePath,
+ PSObject psObjectGetInfo)
+ {
+ if (psObjectGetInfo.BaseObject is PSGetResourceInfo psGetInfo)
+ {
+ if (! psGetInfo.TryWrite(filePath, out string errorMsg))
+ {
+ throw new PSInvalidOperationException(errorMsg);
+ }
+
+ return;
+ }
+
+ throw new PSArgumentException("psObjectGetInfo argument is not a PSGetResourceInfo type.");
+ }
}
#endregion
diff --git a/test/PSGetModuleInfo.xml b/test/PSGetModuleInfo.xml
new file mode 100644
index 000000000..082a4ebac
--- /dev/null
+++ b/test/PSGetModuleInfo.xml
@@ -0,0 +1,152 @@
+
+
+
+ Microsoft.PowerShell.Commands.PSRepositoryItemInfo
+ System.Management.Automation.PSCustomObject
+ System.Object
+
+
+ Microsoft.PowerShell.SecretManagement
+ 1.0.0
+ Module
+ This module provides a convenient way for a user to store and retrieve secrets. The secrets are_x000D__x000A_stored in registered extension vaults. An extension vault can store secrets locally or remotely._x000D__x000A_SecretManagement coordinates access to the secrets through the registered vaults._x000D__x000A__x000D__x000A_Go to GitHub for more information about the module and to submit issues:_x000D__x000A_https://github.com/powershell/SecretManagement
+ Microsoft Corporation
+ Microsoft Corporation
+ (c) Microsoft Corporation. All rights reserved.
+ 2021-03-25T18:08:10-07:00
+
+ 2021-03-25T11:12:41.7662015-07:00
+
+
+
+ Microsoft.PowerShell.Commands.DisplayHintType
+ System.Enum
+ System.ValueType
+ System.Object
+
+ DateTime
+ 2
+
+
+
+
+ https://github.com/PowerShell/SecretManagement/blob/master/LICENSE
+ https://github.com/powershell/secretmanagement
+
+
+
+ System.Object[]
+ System.Array
+ System.Object
+
+
+ PSModule
+ PSEdition_Core
+
+
+
+
+ System.Collections.Hashtable
+ System.Object
+
+
+
+ DscResource
+
+
+
+
+
+
+ RoleCapability
+
+
+
+ Function
+
+
+
+ Cmdlet
+
+
+
+ Register-SecretVault
+ Unregister-SecretVault
+ Get-SecretVault
+ Set-SecretVaultDefault
+ Test-SecretVault
+ Set-Secret
+ Set-SecretInfo
+ Get-Secret
+ Get-SecretInfo
+ Remove-Secret
+
+
+
+
+ Command
+
+
+
+ Register-SecretVault
+ Unregister-SecretVault
+ Get-SecretVault
+ Set-SecretVaultDefault
+ Test-SecretVault
+ Set-Secret
+ Set-SecretInfo
+ Get-Secret
+ Get-SecretInfo
+ Remove-Secret
+
+
+
+
+ Workflow
+
+
+
+
+
+
+
+
+
+
+ https://www.powershellgallery.com/api/v2
+ PSGallery
+ NuGet
+
+
+ System.Management.Automation.PSCustomObject
+ System.Object
+
+
+ (c) Microsoft Corporation. All rights reserved.
+ This module provides a convenient way for a user to store and retrieve secrets. The secrets are_x000D__x000A_stored in registered extension vaults. An extension vault can store secrets locally or remotely._x000D__x000A_SecretManagement coordinates access to the secrets through the registered vaults._x000D__x000A__x000D__x000A_Go to GitHub for more information about the module and to submit issues:_x000D__x000A_https://github.com/powershell/SecretManagement
+ False
+ True
+ True
+ 0
+ 15034
+ 55046
+ 3/25/2021 6:08:10 PM -07:00
+ 3/25/2021 6:08:10 PM -07:00
+ 3/25/2021 6:08:10 PM -07:00
+ PSModule PSEdition_Core PSCmdlet_Register-SecretVault PSCommand_Register-SecretVault PSCmdlet_Unregister-SecretVault PSCommand_Unregister-SecretVault PSCmdlet_Get-SecretVault PSCommand_Get-SecretVault PSCmdlet_Set-SecretVaultDefault PSCommand_Set-SecretVaultDefault PSCmdlet_Test-SecretVault PSCommand_Test-SecretVault PSCmdlet_Set-Secret PSCommand_Set-Secret PSCmdlet_Set-SecretInfo PSCommand_Set-SecretInfo PSCmdlet_Get-Secret PSCommand_Get-Secret PSCmdlet_Get-SecretInfo PSCommand_Get-SecretInfo PSCmdlet_Remove-Secret PSCommand_Remove-Secret PSIncludes_Cmdlet
+ False
+ 2021-03-25T18:08:10Z
+ 1.0.0
+ Microsoft Corporation
+ false
+ Module
+ Microsoft.PowerShell.SecretManagement.nuspec|Microsoft.PowerShell.SecretManagement.dll|Microsoft.PowerShell.SecretManagement.format.ps1xml|Microsoft.PowerShell.SecretManagement.psd1|en-US\about_Microsoft.PowerShell.SecretManagement.help.txt|en-US\Microsoft.PowerShell.SecretManagement.dll-Help.xml
+ a5c858f6-4a8e-41f1-b1ee-0ff8f6ad69d3
+ 5.1
+ Microsoft Corporation
+
+
+ C:\Users\paulhi\OneDrive - Microsoft\Documents\PowerShell\Modules\Microsoft.PowerShell.SecretManagement\1.0.0
+
+
+
diff --git a/test/PSGetResourceInfo.Tests.ps1 b/test/PSGetResourceInfo.Tests.ps1
new file mode 100644
index 000000000..023c23c18
--- /dev/null
+++ b/test/PSGetResourceInfo.Tests.ps1
@@ -0,0 +1,54 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+
+Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force
+
+$psGetMod = Get-Module -Name PowerShellGet
+if ((! $psGetMod) -or (($psGetMod | Select-Object Version) -lt 3.0.0))
+{
+ Write-Verbose -Message "Importing PowerShellGet 3.0.0 for test" -Verbose
+ Import-Module -Name PowerShellGet -MinimumVersion 3.0.0 -Force
+}
+
+Describe "Read PSGetModuleInfo xml file" -tags 'CI' {
+
+ BeforeAll {
+ $fileToRead = Join-Path -Path $PSScriptRoot -ChildPath "PSGetModuleInfo.xml"
+ }
+
+ It "Verifies expected error with null path" {
+ { [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::ReadPSGetResourceInfo($null) } | Should -Throw -ErrorId 'PSInvalidOperationException'
+ }
+
+ It "Verifies expected error with invalid file path" {
+ { [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::ReadPSGetResourceInfo('nonePath') } | Should -Throw -ErrorId 'PSInvalidOperationException'
+ }
+
+ It "Verifies PSGetModuleInfo.xml file is read successfully" {
+ $psGetInfo = [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::ReadPSGetResourceInfo($fileToRead)
+ CheckForExpectedPSGetInfo $psGetInfo
+ }
+}
+
+Describe "Write PSGetModuleInfo xml file" -tags 'CI' {
+
+ BeforeAll {
+ $fileToRead = Join-Path -Path $PSScriptRoot -ChildPath "PSGetModuleInfo.xml"
+ $fileToWrite = Join-Path -Path $TestDrive -ChildPath "PSGetModuleInfo_Write.xml"
+ }
+
+ It "Verifies expected error with null path" {
+ $psGetInfo = [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::ReadPSGetResourceInfo($fileToRead)
+ { [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::WritePSGetResourceInfo($null, $psGetInfo) } | Should -Throw -ErrorId 'PSInvalidOperationException'
+ }
+
+ It "Verifies file write is successful" {
+ $psGetInfo = [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::ReadPSGetResourceInfo($fileToRead)
+ { [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::WritePSGetResourceInfo($fileToWrite, $psGetInfo) } | Should -Not -Throw
+ }
+
+ It "Verifes written file can be read successfully" {
+ $newGetInfo = [Microsoft.PowerShell.PowerShellGet.UtilClasses.TestHooks]::ReadPSGetResourceInfo($fileToWrite)
+ CheckForExpectedPSGetInfo $newGetInfo
+ }
+}
diff --git a/test/PSGetTestUtils.psm1 b/test/PSGetTestUtils.psm1
index ca57a7294..bfeaea5a2 100644
--- a/test/PSGetTestUtils.psm1
+++ b/test/PSGetTestUtils.psm1
@@ -1,10 +1,5 @@
-<#####################################################################################
- # File: PSGetTestUtils.psm1
- #
- # Copyright (c) Microsoft Corporation, 2020
- #####################################################################################>
-
-#."$PSScriptRoot\uiproxy.ps1"
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
$psGetMod = Get-Module -Name PowerShellGet
if ((! $psGetMod) -or (($psGetMod | Select-Object Version) -lt 3.0.0))
@@ -450,3 +445,60 @@ $($ReleaseNotes -join "`r`n")
return $PSScriptInfoString
}
}
+
+<#
+Checks that provided PSGetInfo object contents match the expected data
+from the test information file: PSGetModuleInfo.xml
+#>
+function CheckForExpectedPSGetInfo
+{
+ param ($psGetInfo)
+
+ $psGetInfo.AdditionalMetadata.Keys | Should -HaveCount 22
+ $psGetInfo.AdditionalMetadata['copyright'] | Should -BeExactly '(c) Microsoft Corporation. All rights reserved.'
+ $psGetInfo.AdditionalMetadata['description'] | Should -BeLike 'This module provides a convenient way for a user to store and retrieve secrets*'
+ $psGetInfo.AdditionalMetadata['requireLicenseAcceptance'] | Should -BeExactly 'False'
+ $psGetInfo.AdditionalMetadata['isLatestVersion'] | Should -BeExactly 'True'
+ $psGetInfo.AdditionalMetadata['isAbsoluteLatestVersion'] | Should -BeExactly 'True'
+ $psGetInfo.AdditionalMetadata['versionDownloadCount'] | Should -BeExactly '0'
+ $psGetInfo.AdditionalMetadata['downloadCount'] | Should -BeExactly '15034'
+ $psGetInfo.AdditionalMetadata['packageSize'] | Should -BeExactly '55046'
+ $psGetInfo.AdditionalMetadata['published'] | Should -BeExactly '3/25/2021 6:08:10 PM -07:00'
+ $psGetInfo.AdditionalMetadata['created'] | Should -BeExactly '3/25/2021 6:08:10 PM -07:00'
+ $psGetInfo.AdditionalMetadata['lastUpdated'] | Should -BeExactly '3/25/2021 6:08:10 PM -07:00'
+ $psGetInfo.AdditionalMetadata['tags'] | Should -BeLike 'PSModule PSEdition_Core PSCmdlet_Register-SecretVault*'
+ $psGetInfo.AdditionalMetadata['developmentDependency'] | Should -BeExactly 'False'
+ $psGetInfo.AdditionalMetadata['updated'] | Should -BeExactly '2021-03-25T18:08:10Z'
+ $psGetInfo.AdditionalMetadata['NormalizedVersion'] | Should -BeExactly '1.0.0'
+ $psGetInfo.AdditionalMetadata['Authors'] | Should -BeExactly 'Microsoft Corporation'
+ $psGetInfo.AdditionalMetadata['IsPrerelease'] | Should -BeExactly 'false'
+ $psGetInfo.AdditionalMetadata['ItemType'] | Should -BeExactly 'Module'
+ $psGetInfo.AdditionalMetadata['FileList'] | Should -BeLike 'Microsoft.PowerShell.SecretManagement.nuspec|Microsoft.PowerShell.SecretManagement.dll*'
+ $psGetInfo.AdditionalMetadata['GUID'] | Should -BeExactly 'a5c858f6-4a8e-41f1-b1ee-0ff8f6ad69d3'
+ $psGetInfo.AdditionalMetadata['PowerShellVersion'] | Should -BeExactly '5.1'
+ $psGetInfo.AdditionalMetadata['CompanyName'] | Should -BeExactly 'Microsoft Corporation'
+ #
+ $psGetInfo.Author | Should -BeExactly 'Microsoft Corporation'
+ $psGetInfo.CompanyName | Should -BeExactly 'Microsoft Corporation'
+ $psGetInfo.Copyright | Should -BeExactly '(c) Microsoft Corporation. All rights reserved.'
+ $psGetInfo.Dependencies | Should -HaveCount 0
+ $psGetInfo.Description | Should -BeLike 'This module provides a convenient way for a user to store*'
+ $psGetInfo.IconUri | Should -BeNullOrEmpty
+ $psGetInfo.Includes.Cmdlet | Should -HaveCount 10
+ $psGetInfo.Includes.Cmdlet[0] | Should -BeExactly 'Register-SecretVault'
+ $psGetInfo.InstalledDate.Year | Should -BeExactly 2021
+ $psGetInfo.InstalledLocation | Should -BeLike 'C:\Users\*'
+ $psGetInfo.LicenseUri | Should -BeExactly 'https://github.com/PowerShell/SecretManagement/blob/master/LICENSE'
+ $psGetInfo.Name | Should -BeExactly 'Microsoft.PowerShell.SecretManagement'
+ $psGetInfo.PackageManagementProvider | Should -BeExactly 'NuGet'
+ $psGetInfo.PowerShellGetFormatVersion | Should -BeNullOrEmpty
+ $psGetInfo.ProjectUri | Should -BeExactly 'https://github.com/powershell/secretmanagement'
+ $psGetInfo.PublishedDate.Year | Should -BeExactly 2021
+ $psGetInfo.ReleasedNotes | Should -BeNullOrEmpty
+ $psGetInfo.Repository | Should -BeExactly 'PSGallery'
+ $psGetInfo.RepositorySourceLocation | Should -BeExactly 'https://www.powershellgallery.com/api/v2'
+ $psGetInfo.Tags | Should -BeExactly @('PSModule', 'PSEdition_Core')
+ $psGetInfo.Type | Should -BeExactly 'Module'
+ $psGetInfo.UpdatedDate.Year | Should -BeExactly 1
+ $psGetInfo.Version.ToString() | Should -BeExactly '1.0.0'
+}
diff --git a/test/toBeRemoved.txt b/test/toBeRemoved.txt
deleted file mode 100644
index e69de29bb..000000000