Koans/Introduction/AboutCmdletVerbs.Koans.ps1

using module PSKoans
[Koan(Position = 105)]
param()
<#
    Cmdlet Verbs

    The fundamental building block of PowerShell are cmdlets and functions, both
    of which are named according to a Verb-Noun syntax by convention.

    You can see the list of PowerShell's recommended / approved verbs by calling
    Get-Verb in your PowerShell console, or going to the following docs page:
    https://docs.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands

    Each command should use a verb appropriate to the action it's taking, and a
    noun that succinctly and clearly describes what it's acting upon.

    In this topic, we'll cover a few of the most common verbs which you'll see
    most frequently.
#>


Describe "Basic Verbs" {

    BeforeAll {
        # We'll be using this path later on.
        $FilePath = "$env:TMP/YOUR_PATH.txt"

        if (Test-Path $FilePath) {
            Remove-Item -Path $FilePath
        }
    }

    Context "Get" {
        <#
            Cmdlets with the Get verb are used for retrieving data.

            So for example "Get-Process" will retrieve all the processes running
            on your current machine.
        #>


        It 'is for commands that retrieve data' {
            <#
                Using the Get-Command cmdlet, which retrieves all available
                commands, find 5 commands with the Get verb.

                Fill in each blank with the name of a different Get-* command.
            #>

            $Answers = @(
                "____"
                "____"
                "____"
                "____"
                "____"
            )
            $Answers | Should -BeIn (Get-Command -Verb Get).Name

            $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required"
        }
    }

    Context "New" {
        <#
            Cmdlets with the New verb are used to create data.

            So for example 'New-Guid' will create a new GUID, or 'New-TimeSpan'
            will create a new [timespan] object with the specified parameters.
        #>


        It 'is for commands that create data' {
            <#
                Using Get-Command, find 5 commands with the New verb.

                Replace each ____ with the name of a New-* command.
            #>

            $Answers = @(
                "____"
                "____"
                "____"
                "____"
                "____"
            )
            $Answers | Should -BeIn (Get-Command -Verb New).Name

            $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required"
        }

        It 'can create a New-Item' {
            <#
                Let's try creating a file!

                Use New-Item to create a new text file, in the location
                specified with the $FilePath variable, which is defined above.

                The necessary parameters are already filled in for you here. In
                this case, the file we're creating is simply empty. You could
                also specify a -Value parameter with some text to put in the
                newly-created file.

                Take some time to experiment with New-Item in your console if
                you'd like to see what it can do! Start with:

                    Get-Command New-Item -Syntax
                    Get-Help New-Item -Examples
            #>


            $File = ____ -Path $FilePath -ItemType File

            # All "file" objects are of this type.
            $File | Should -BeOfType [System.IO.FileInfo]

            # An empty file has a "length" of zero.
            $File.Length | Should -Be 0
        }
    }

    Context "Add" {
        <#
            Cmdlets with the Add verb append data to an existing object or data
            source.

            Essentially, if the target doesn't exist then a cmdlet with the Add
            verb will typically create it. If it does exist, the cmdlet will
            add data to it, if data can be added without overwriting the
            original data.

            A common example one might see working with Office 365 is calendar
            permissions. If you want to grant permissions to somebody who
            doesn't have any, you use "Add-MailboxFolderPermission".
        #>


        It 'is for commands that append data' {
            <#
                Using Get-Command, find 5 commands with the Add verb.

                Replace each ____ with the name of an Add-* command.
            #>

            $Answers = "____", "____", "____", "____", "____"
            $Answers | Should -BeIn (Get-Command -Verb Add).Name

            $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required"
        }

        It 'can Add-Content to a file' {
            <#
                Try adding this content to the file we created above using
                Add-Content.
            #>

            "Mountains are merely mountains." | ____ -Path $FilePath

            <#
                Let's see what happens if we add a whole bunch of things! Fill
                in these blanks with whatever you like.
            #>


            '____' | Add-Content -Path $FilePath
            '____' | Add-Content -Path $FilePath
            '____' | Add-Content -Path $FilePath
            '____' | Add-Content -Path $FilePath

            # Let's check the contents of the file.
            $FileData = Get-Content -Path $FilePath

            # How many lines did we end up with?
            __ | Should -Be $FileData.Count

            <#
                We can see that several lines of content were added to the file.
                Add-* cmdlets can only append data, they can't overwrite. With
                this information, you should be able to determine what the
                expected content of the file is at this point.
            #>


            $ExpectedContent = @(
                'Mountains are merely mountains.'
                '____'
                '____'
                '____'
                'The road onwards, the road back; which is the shorter?'
            )

            $ExpectedContent | Should -BeExactly $FileData
        }
    }

    Context "Set" {
        <#
            Cmdlets with the Set verb will overwrite information that already
            exists.

            Some Set-* cmdlets require the instance to already be present for
            you to change it; you'll need to use a New-* cmdlet first to create
            an instance before you can overwrite information within it.

            A common example one may see working with Office 365 is with
            calendar permissions. If a user already has some permissions
            configured, you can use "Set-MailboxFolderPermission" to change the
            user's permissions.
        #>


        It 'is for commands that overwrite data' {
            <#
                Using Get-Command, find 5 commands with the Set verb.

                Replace each ____ with the name of a Set-* command.
            #>

            $Answers = "____", "____", "____", "____", "____"
            $Answers | Should -BeIn (Get-Command -Verb Set).Name

            $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required"
        }

        It 'can Set-Content for a file' {
            <#
                Let's try using Set-Content on our text file from before. But
                first, let's check that it still has the contents we added. We
                should still have 5 lines in it from before.

                If you added extra lines to the file in the Add-Content koan
                above, make sure to update the expected line count here!
            #>

            $LineCount = 5
            Get-Content -Path $FilePath | Should -HaveCount $LineCount

            # Now let's try setting the contents.
            "Wherever you are, it's the place you need to be." | Set-Content -Path $FilePath

            # So what should be in the file now?
            $FileContent = Get-Content -Path $FilePath
            "____" | Should -BeExactly $FileContent

            # What happens if we set the contents again?
            '____' | Set-Content -Path $FilePath
            Get-Content -Path $FilePath | Should -BeExactly "Rest and be kind, you don't have to prove anything."
            <#
                You'll see that there's only one line of text in the file. This
                is because the Set-Content command will completely overwrite
                whatever is in the file already.
            #>

        }
    }

    Context "Remove" {
        <#
            Cmdlets with the Remove verb will delete data from an object or data
            source.

            Once again with calendar permissions in Office 365, you can use a
            Remove cmdlet to completely remove a user's permissions to a
            calendar.
            #>


        It "is for commands that delete data" {
            <#
            Using Get-Command, find 5 commands with the Remove verb.

            Replace each ____ with the name of a Remove-* command.
        #>

            $Answers = "____", "____", "____", "____", "____"
            $Answers | Should -BeIn (Get-Command -Verb Remove).Name

            $Answers | Get-Unique | Should -HaveCount 5 -Because "five unique cmdlets are required"
        }

        It 'can Remove-Item to delete a file' {
            <#
                    We can use Remove-Item to delete the text file we've been
                    working with. Before we do, let's just double check the file
                    still exists. 'Leaf' here refers to a file; 'Container'
                    would be the corresponding type for a folder.
                #>

            Test-Path $FilePath -PathType Leaf | Should -BeTrue

            # Pester has its own way of checking that files exist.
            $FilePath | Should -Exist

            # Use Remove-item to delete the file completely.
            ____ -Path $FilePath

            # Let's check it was removed properly. Test-Path $FilePath -PathType Leaf | Should -BeTrue
            Test-Path $FilePath | Should -BeFalse

            <#
                    If we try to remove a file that doesn't exist, we should get
                    an error. What does that error look like?
                #>

            $Message = "____"
            { Remove-Item -Path $FilePath -ErrorAction Stop } | Should -Throw -ExpectedMessage $Message
        }
    }
}