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