Skip to content

Commit

Permalink
✨ Add specific error for Show-Advice (#287)
Browse files Browse the repository at this point in the history
* ✨ Add specific error for Show-Advice

* Update PSKoans/Public/Show-Advice.ps1

Co-Authored-By: Joel Sallow (/u/ta11ow) <32407840+vexx32@users.noreply.github.com>

* Update PSKoans/Public/Show-Advice.ps1

Co-Authored-By: Joel Sallow (/u/ta11ow) <32407840+vexx32@users.noreply.github.com>

* Update PSKoans/Public/Show-Advice.ps1

Co-Authored-By: Joel Sallow (/u/ta11ow) <32407840+vexx32@users.noreply.github.com>

* Update PSKoans/Public/Show-Advice.ps1

Co-Authored-By: Joel Sallow (/u/ta11ow) <32407840+vexx32@users.noreply.github.com>

* Adjust tests to new errors

* Remove unnecessary var initialization
  • Loading branch information
robdy authored and vexx32 committed Oct 22, 2019
1 parent 29fd4d1 commit 54beee2
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 96 deletions.
2 changes: 1 addition & 1 deletion PSKoans/Data/Advice/Customization/Profile.Advice.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
"To create or open the profile file, simply run:",
" notepad $profile"
]
}
}
48 changes: 24 additions & 24 deletions PSKoans/Data/Advice/Fun/FunWithCats.Advice.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
{
"Title": "Fun with Cat Facts",
"Content": [
"PowerShell doesn't have to all be about Server administration, ops, or automation.",
"\n",
"It can also be fun!",
"\n",
"We've provided some fun examples below just to give you a taste of what PowerShell can do",
"Cats",
"\n",
" The below code snippit will query a RESTAPI on the internet that provides some fun facts about cats. It then uses the SpeechSynthesizer to tell you these facts! Feel free to run it on your machine:",
"\n",
"function Get-CatFact {",
"\n",
"\tAdd-Type -AssemblyName System.Speech",
"\t$SpeechSynth = New-Object System.Speech.Synthesis.SpeechSynthesizer",
"\t$URI = 'http://www.catfact.info/api/v1/facts.json?per_page=200'",
"\t$Random = Get-Random -Maximum 200",
"\t$CatFact = (ConvertFrom-Json (Invoke-WebRequest -Uri $URI)).Facts[$Random]",
"\t$SpeechSynth.Speak('did you know?')",
"\t$SpeechSynth.Speak($CatFact.details)",
"}",
"\n",
"Get-CatFact"
]
"Title": "Fun with Cat Facts",
"Content": [
"PowerShell doesn't have to all be about Server administration, ops, or automation.",
"\n",
"It can also be fun!",
"\n",
"We've provided some fun examples below just to give you a taste of what PowerShell can do",
"Cats",
"\n",
" The below code snippit will query a RESTAPI on the internet that provides some fun facts about cats. It then uses the SpeechSynthesizer to tell you these facts! Feel free to run it on your machine:",
"\n",
"function Get-CatFact {",
"\n",
"\tAdd-Type -AssemblyName System.Speech",
"\t$SpeechSynth = New-Object System.Speech.Synthesis.SpeechSynthesizer",
"\t$URI = 'http://www.catfact.info/api/v1/facts.json?per_page=200'",
"\t$Random = Get-Random -Maximum 200",
"\t$CatFact = (ConvertFrom-Json (Invoke-WebRequest -Uri $URI)).Facts[$Random]",
"\t$SpeechSynth.Speak('did you know?')",
"\t$SpeechSynth.Speak($CatFact.details)",
"}",
"\n",
"Get-CatFact"
]
}
70 changes: 35 additions & 35 deletions PSKoans/Data/Advice/Fun/FunWithGUIs.Advice.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
{
"Title": "Fun with GUIs",
"Content": [
"PowerShell doesn't have to all be about Server administration, ops, or automation.",
"It can also be fun!",
"\n",
"We've provided some fun examples below just to give you a taste of what PowerShell can do",
"\n",
"GUIs",
"\n",
"\tThe below code snippit will make a blue GUI. When you're more experienced you may",
"\twant to start making GUIs for your scripts. This is just a quick example.",
"\n",
"\tCopy the below into PowerShell ISE to create the GUI!",
"\n",
"# Import Assemblies ",
"[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Drawing')",
"[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')",
"\n",
"\n",
"# Create a new form object and assign it to the variable GUIExample",
"$GUIExample = New-Object System.Windows.Forms.Form",
"\n",
"# Define the background image and then set the form to be the same height/width as the image",
"$BackgroundImage = [System.Drawing.Image]",
"$GUIExample.BackColor = 'Blue'",
"$GUIExample.Width = 200",
"$GUIExample.Height = 400",
"\n",
"# Make the GUI the topmost window and give it focus (make it the selected window)",
"$GUIExample.TopMost = $True",
"$GUIExample.Add_Shown({$GUIExample.Activate()})",
"\n",
"# Show the GUI",
"[void]$GUIExample.ShowDialog()"
]
"Title": "Fun with GUIs",
"Content": [
"PowerShell doesn't have to all be about Server administration, ops, or automation.",
"It can also be fun!",
"\n",
"We've provided some fun examples below just to give you a taste of what PowerShell can do",
"\n",
"GUIs",
"\n",
"\tThe below code snippit will make a blue GUI. When you're more experienced you may",
"\twant to start making GUIs for your scripts. This is just a quick example.",
"\n",
"\tCopy the below into PowerShell ISE to create the GUI!",
"\n",
"# Import Assemblies ",
"[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Drawing')",
"[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')",
"\n",
"\n",
"# Create a new form object and assign it to the variable GUIExample",
"$GUIExample = New-Object System.Windows.Forms.Form",
"\n",
"# Define the background image and then set the form to be the same height/width as the image",
"$BackgroundImage = [System.Drawing.Image]",
"$GUIExample.BackColor = 'Blue'",
"$GUIExample.Width = 200",
"$GUIExample.Height = 400",
"\n",
"# Make the GUI the topmost window and give it focus (make it the selected window)",
"$GUIExample.TopMost = $True",
"$GUIExample.Add_Shown({$GUIExample.Activate()})",
"\n",
"# Show the GUI",
"[void]$GUIExample.ShowDialog()"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"Content": [
"When typing a parameter or the value for a parameter, you can hit the TAB key to cycle through the options available. While this is generally well known, it is LESS well known, that by hitting \"CTRL\"+\"SpaceBar\" you can show all available options at once and use the cursor keys to navigate to the option you want."
]
}
}
2 changes: 1 addition & 1 deletion PSKoans/Data/Advice/Interactive/EditMode.Advice.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
" Set-PSReadlineOption -EditMode Vi",
" Set-PSReadlineOption -EditMode Windows"
]
}
}
61 changes: 30 additions & 31 deletions PSKoans/Data/Advice/OOP/OOPIntroduction.Advice.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
{
"Title": "Object-Orientated Programming (OOP) Introduction",
"Content": [

"PowerShell is an object-oriented shell, but what does this mean? Everything is an object!",
"\n",
"Objects are a way for us to build programs to scale, and OOP is standard in software development. There are three fundamentals you need to know:",
"\n",
"\t1. Objects have defined types, which are like blueprints",
"\t2. Objects store data in properties",
"\t3. Objects have methods which can be called to perform an action",
"\n",
"If you've already completed the Get-Member topic, then you'll know we can use this cmdlet to discover what blueprint an object is using, what properties it has, and what methods it may execute. For example, we may take a string and pass it into Get-Member in order to get the below result:",
"\n",
"\t\tTypeName: System.String",
"\n",
"\tName MemberType Definition",
"\t---- ---------- ----------",
"\tClone Method System.Object Clone(), System.Object ICloneable.Clone()",
"\tLength Property int Length {get;}",
"\n",
"Which shows us the object type (System.String), as well as some properties and methods.",
"\n",
"For more information please see the below articles on OOP concepts:",
"\n",
"\t Abstraction: https://stackify.com/oop-concept-abstraction/",
"\t Encapsulation: https://stackify.com/oop-concept-for-beginners-what-is-encapsulation/",
"\t Inheritance: https://stackify.com/oop-concept-inheritance/",
"\t Polymorphism: https://stackify.com/oop-concept-polymorphism/",
"\n",
"The .NET Core API browser may also be useful given that .NET is the foundation on which PowerShell is built: https://docs.microsoft.com/en-us/dotnet/api/?view=netcore-3.0"
]
"Title": "Object-Orientated Programming (OOP) Introduction",
"Content": [
"PowerShell is an object-oriented shell, but what does this mean? Everything is an object!",
"\n",
"Objects are a way for us to build programs to scale, and OOP is standard in software development. There are three fundamentals you need to know:",
"\n",
"\t1. Objects have defined types, which are like blueprints",
"\t2. Objects store data in properties",
"\t3. Objects have methods which can be called to perform an action",
"\n",
"If you've already completed the Get-Member topic, then you'll know we can use this cmdlet to discover what blueprint an object is using, what properties it has, and what methods it may execute. For example, we may take a string and pass it into Get-Member in order to get the below result:",
"\n",
"\t\tTypeName: System.String",
"\n",
"\tName MemberType Definition",
"\t---- ---------- ----------",
"\tClone Method System.Object Clone(), System.Object ICloneable.Clone()",
"\tLength Property int Length {get;}",
"\n",
"Which shows us the object type (System.String), as well as some properties and methods.",
"\n",
"For more information please see the below articles on OOP concepts:",
"\n",
"\t Abstraction: https://stackify.com/oop-concept-abstraction/",
"\t Encapsulation: https://stackify.com/oop-concept-for-beginners-what-is-encapsulation/",
"\t Inheritance: https://stackify.com/oop-concept-inheritance/",
"\t Polymorphism: https://stackify.com/oop-concept-polymorphism/",
"\n",
"The .NET Core API browser may also be useful given that .NET is the foundation on which PowerShell is built: https://docs.microsoft.com/en-us/dotnet/api/?view=netcore-3.0"
]
}
22 changes: 22 additions & 0 deletions PSKoans/Public/Show-Advice.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@
Get-Content |
ConvertFrom-Json

# Checking for errors
if (-not $AdviceObject) {
$ErrorDetails = @{
ExceptionType = 'System.IO.FileNotFoundException'
ExceptionMessage = 'Could not find any Advice files matching the specified Name: {0}.' -f $Name
ErrorId = 'PSKoans.NoMatchingAdviceFound'
ErrorCategory = 'ObjectNotFound'
TargetObject = $Name
}
$PSCmdlet.ThrowTerminatingError( (New-PSKoanErrorRecord @ErrorDetails) )
}
elseif (-not ($AdviceObject.Title -and $AdviceObject.Content)) {
$ErrorDetails = @{
ExceptionType = 'System.IO.FileLoadException'
ExceptionMessage = 'Could not find Title and/or Content elements for Advice file: {0}' -f $Name
ErrorId = 'PSKoans.IncorrectAdviceData'
ErrorCategory = 'InvalidData'
TargetObject = $Name
}
$PSCmdlet.ThrowTerminatingError( (New-PSKoanErrorRecord @ErrorDetails) )
}

$AdviceObject.Title | Write-ConsoleLine -Title
$AdviceObject.Content | Write-ConsoleLine
}
Expand Down
42 changes: 39 additions & 3 deletions Tests/Functions/Public/Show-Advice.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ InModuleScope 'PSKoans' {

BeforeAll{
Mock Write-ConsoleLine { }
# Exporting incorrect advices to the folder
$AdviceFolder = $script:ModuleRoot | Join-Path -ChildPath 'Data/Advice'
$AdviceObject = Get-ChildItem -Path $AdviceFolder -Recurse -File -Filter "*.Advice.json"
$RandomAdvicesFilePaths = ($AdviceObject | Get-Random -Count 3).FullName
$Backup = $RandomAdvicesFilePaths | ForEach-Object {Get-Content $_ | ConvertFrom-Json}
}

Context "Behaviour of Parameter-less Calls" {
Expand Down Expand Up @@ -36,9 +41,40 @@ InModuleScope 'PSKoans' {
}

It "should throw an error if the requested file cannot be found" {
$message = "Cannot validate argument on parameter 'InputString'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again."

{ Show-Advice -Name "ThisDoesntExist" -ErrorAction Stop } | Should -Throw -ExpectedMessage $message
$message = "Could not find any Advice files matching the specified Name: ThisDoesntExist"
{ Show-Advice -Name "ThisDoesntExist" -ErrorAction Stop } | Should -Throw -ExpectedMessage $Message
}

# Creating incorrect Advice
$IncorrectObjectsData = @(
@{
NotTitle = "Fake title"
NotContent = @(1..4 | ForEach-Object {"Fake line $_"})
},
@{
Content = @(1..4 | ForEach-Object {"Fake line $_"})
},
@{
Title = "Fake title"
}
)
for ($i = 0; $i -lt 3; $i++) {
$IncorrectObjectsData[$i] | ConvertTo-Json | Out-File $RandomAdvicesFilePaths[$i]
}

It "should throw an error if the requested file's format is not correct" {
for ($i = 0; $i -lt 3; $i++) {
$AdviceName = (Get-Item $RandomAdvicesFilePaths[$i]).BaseName -replace('^(.*)(?:.Advice)','$1')
$Message = "Could not find Title and/or Content elements for Advice file: {0}" -f $AdviceName
{ Show-Advice -Name $AdviceName -ErrorAction Stop } | Should -Throw -ExpectedMessage $Message
}
}

}

AfterAll{
for ($i = 0; $i -lt 3; $i++) {
Set-Content -Path ((Get-Item $RandomAdvicesFilePaths[$i]).FullName) -Value ($Backup[$i] | ConvertTo-Json)
}
}
}
Expand Down

0 comments on commit 54beee2

Please sign in to comment.