Skip to content

Commit

Permalink
✨ Add "Open File" Feature (#346)
Browse files Browse the repository at this point in the history
* ✨ Add Line info in Get-Karma result

* ✨ Add params to open current file

- Move `-Meditate` to open the current file
- Add `-Library` to open the folder.

* ♻️ Cleanup extra brace

* 📝 Update help files

* 🔧 Fix error in Show-Karma

* 🔧  Add embedded quotes for default case

* 🐛 Check to ensure koan location exists

When Get-PSKoan is called with the user scope it needs to check if the
folder actually exists.

* ♻️ Streamline Show-Karma editor logic

* ✅ Update tests

- Use temp dir in show-karma test

- Restructure tests to avoid duplication
  • Loading branch information
vexx32 committed Jan 27, 2020
1 parent 657bdea commit c450201
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 69 deletions.
8 changes: 5 additions & 3 deletions PSKoans/Public/Get-Karma.ps1
Expand Up @@ -32,6 +32,7 @@
'ModuleOnly' { $GetParams['Module'] = $Module }
{ $Topic } { $GetParams['Topic'] = $Topic }
}

switch ($PSCmdlet.ParameterSetName) {
'ListKoans' {
Get-PSKoan @GetParams
Expand Down Expand Up @@ -110,9 +111,10 @@
KoansPassed = $KoansPassed
TotalKoans = $TotalKoans
CurrentTopic = [PSCustomObject]@{
Name = $KoanFile.Topic
Completed = $PesterTests.PassedCount
Total = $PesterTests.TotalCount
Name = $KoanFile.Topic
Completed = $PesterTests.PassedCount
Total = $PesterTests.TotalCount
CurrentLine = ($NextKoanFailed.StackTrace -split '\r?\n')[1] -replace ':.+'
}
Results = $PesterTests.TestResult
RequestedTopic = $Topic
Expand Down
11 changes: 10 additions & 1 deletion PSKoans/Public/Get-PSKoan.ps1
Expand Up @@ -32,7 +32,16 @@ function Get-PSKoan {
)

$ParentPath = switch ($Scope) {
'User' { Get-PSKoanLocation }
'User' {
$KoanLocation = Get-PSKoanLocation
Write-Verbose "Checking existence of koans folder"
if (-not (Test-Path $KoanLocation)) {
Write-Verbose "Koans folder does not exist. Initiating full reset..."
Update-PSKoan -Confirm:$false
}

$KoanLocation
}
'Module' { Join-Path -Path $script:ModuleRoot -ChildPath 'Koans' }
}

Expand Down
41 changes: 40 additions & 1 deletion PSKoans/Public/Show-Karma.ps1
Expand Up @@ -29,11 +29,16 @@ function Show-Karma {
[switch]
$List,

[Parameter(Mandatory, ParameterSetName = 'OpenFolder')]
[Parameter(Mandatory, ParameterSetName = 'OpenFile')]
[Alias('Meditate')]
[switch]
$Contemplate,

[Parameter(Mandatory, ParameterSetName = 'OpenFolder')]
[Alias('OpenFolder')]
[switch]
$Library,

[Parameter()]
[Alias()]
[switch]
Expand Down Expand Up @@ -80,6 +85,40 @@ function Show-Karma {
$KoanLocation | Invoke-Item
}
}
'OpenFile' {
try {
$Results = Get-Karma @GetParams
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}

$Editor = Get-PSKoanSetting -Name Editor
$FilePath = (Get-PSKoan -Topic $Results.CurrentTopic.Name -Scope User).Path
$LineNumber = $Results.CurrentTopic.CurrentLine

$Arguments = switch ($Editor) {
{ $_ -in 'code', 'code-insiders' } {
'--goto'
'"{0}":{1}' -f (Resolve-Path $FilePath), $LineNumber
'--reuse-window'
}
atom {
'"{0}":{1}' -f (Resolve-Path $FilePath), $LineNumber
}
default {
'"{0}"' -f (Resolve-Path $FilePath)
}
}

if ($Editor -and (Get-Command -Name $Editor -ErrorAction SilentlyContinue)) {
Start-Process -FilePath $Editor -ArgumentList $Arguments
}
else {
Invoke-Item -Path $FilePath
}
}

default {
if ($ClearScreen) {
Clear-Host
Expand Down
208 changes: 149 additions & 59 deletions Tests/Functions/Public/Show-Karma.Tests.ps1
Expand Up @@ -7,6 +7,16 @@ if (-not (Get-Module PSKoans)) {
#endregion

Describe 'Show-Karma' {
BeforeAll {
$StartingLocation = Get-PSKoanLocation
Set-PSKoanLocation -Path "$TestDrive/Koans"

Reset-PSKoan -Confirm:$false
}

AfterAll {
Set-PSKoanLocation -Path $StartingLocation
}

InModuleScope 'PSKoans' {

Expand All @@ -23,9 +33,10 @@ Describe 'Show-Karma' {
Expectation = 'ExpectedTest'
It = 'TestIt'
CurrentTopic = [PSCustomObject]@{
Name = 'TestTopic"'
Completed = 0
Total = 4
Name = 'TestTopic"'
Completed = 0
Total = 4
CurrentLine = 1
}
}
}
Expand Down Expand Up @@ -77,9 +88,10 @@ Describe 'Show-Karma' {
Expectation = 'ExpectedTest'
It = 'TestIt'
CurrentTopic = [PSCustomObject]@{
Name = 'TestTopic"'
Completed = 0
Total = 4
Name = 'TestTopic"'
Completed = 0
Total = 4
CurrentLine = 1
}
}
}
Expand Down Expand Up @@ -109,6 +121,9 @@ Describe 'Show-Karma' {
Mock Get-PSKoan -ModuleName 'PSKoans' { }
Mock Update-PSKoan -ModuleName 'PSKoans' { throw 'Prevent recursion' }
Mock Write-Warning
Mock Test-Path { $false }
Mock Invoke-Item
Mock New-Item
}

It 'should attempt to populate koans and then recurse to reassess' {
Expand All @@ -126,6 +141,22 @@ Describe 'Show-Karma' {
It 'throws an error if a Topic is specified that matches nothing' {
{ Show-Karma -Topic 'AboutAbsolutelyNothing' } | Should -Throw -ErrorId 'PSKoans.TopicNotFound'
}

It 'should create PSKoans directory with -Library' {
{ Show-Karma -Library } | Should -Throw -ExpectedMessage 'Prevent recursion'

Assert-MockCalled Test-Path -Times 1
Assert-MockCalled Update-PSKoan -Times 1
Assert-MockCalled New-Item -Times 1
}

It 'should create PSKoans directory with -Contemplate' {
{ Show-Karma -Contemplate } | Should -Throw -ExpectedMessage 'Prevent recursion'

Assert-MockCalled Test-Path -Times 1
Assert-MockCalled Update-PSKoan -Times 1
Assert-MockCalled New-Item -Times 1
}
}

Context 'With -ListTopics Parameter' {
Expand All @@ -152,9 +183,10 @@ Describe 'Show-Karma' {
Expectation = 'ExpectedTest'
It = 'TestIt'
CurrentTopic = [PSCustomObject]@{
Name = 'TestTopic"'
Completed = 0
Total = 4
Name = 'TestTopic"'
Completed = 0
Total = 4
CurrentLine = 1
}
RequestedTopic = $Topic
}
Expand Down Expand Up @@ -186,73 +218,131 @@ Describe 'Show-Karma' {
}
}

Context 'With -Meditate Switch' {
Context 'With -Contemplate Switch' {
BeforeAll {
$TestFile = New-TemporaryFile

Context 'With "code" Set as the Editor' {
BeforeAll {
Mock Get-Command { $true }
Mock Start-Process {
@{ Editor = $FilePath; Path = $ArgumentList }
Mock Invoke-Item { $Path }
Mock Get-Command { $true } -ParameterFilter { $Name -ne "missing_editor" }
Mock Get-Command { $false } -ParameterFilter { $Name -eq "missing_editor" }
Mock Start-Process {
@{ Editor = $FilePath; Arguments = $ArgumentList }
}
Mock Get-Karma -ModuleName 'PSKoans' {
[PSCustomObject]@{
PSTypeName = 'PSKoans.Result'
Meditation = 'TestMeditation'
KoansPassed = 0
TotalKoans = 400
Describe = 'TestDescribe'
Expectation = 'ExpectedTest'
It = 'TestIt'
CurrentTopic = [PSCustomObject]@{
Name = 'TestTopic"'
Completed = 0
Total = 4
CurrentLine = 1
}
}
Set-PSKoanSetting -Name Editor -Value 'code'

$Result = Show-Karma -Contemplate
}
Mock Get-PSKoan {
[PSCustomObject]@{ Path = $TestFile.FullName }
}
}

It 'should start VS Code with Start-Process' {
$Result.Editor | Should -Be 'code'
AfterAll {
$TestFile | Remove-Item
}

Assert-MockCalled Get-Command -Times 1
Assert-MockCalled Start-Process -Times 1
}
It 'invokes VS Code with "code" set as Editor with proper arguments' {
Set-PSKoanSetting -Name Editor -Value 'code'
$Result = Show-Karma -Contemplate

It 'should pass a resolved path' {
# Resolve-Path doesn't like embedded quotes
$Path = $Result.Path -replace '"'
$Path | Should -BeExactly (Resolve-Path -Path $Path).Path
}
$Result.Editor | Should -BeExactly 'code'
$Result.Arguments[0] | Should -BeExactly '--goto'
$Result.Arguments[1] | Should -MatchExactly '"[^"]+":\d+'
$Result.Arguments[2] | Should -BeExactly '--reuse-window'

It 'should enclose the path in quotes' {
$Result.Path | Should -MatchExactly '"[^"]+"'
}
# Resolve-Path doesn't like embedded quotes
$Path = ($Result.Arguments[1] -split '(?<="):')[0] -replace '"'
$Path | Should -BeExactly (Resolve-Path -Path $Path).Path

Assert-MockCalled Get-Command -Times 1
Assert-MockCalled Start-Process -Times 1
}

Context 'With Editor Not Found' {
BeforeAll {
Mock Get-Command { $false }
Mock Invoke-Item
Set-PSKoanSetting -Name Editor -Value "ascsadsa"
}
It 'invokes the set editor with unknown editor chosen' {
Set-PSKoanSetting -Name Editor -Value 'vim'

It 'should not produce output' {
Show-Karma -Meditate | Should -BeNullOrEmpty
}
$Result = Show-Karma -Contemplate
$Result.Editor | Should -BeExactly 'vim'
$Result.Arguments | Should -MatchExactly '"[^"]+"'

It 'should open the koans directory with Invoke-Item' {
Assert-MockCalled Get-Command -Times 1 -ParameterFilter { $Name -eq "ascsadsa" }
Assert-MockCalled Invoke-Item -Times 1
}
# Resolve-Path doesn't like embedded quotes
$Path = $Result.Arguments -replace '"'
$Path | Should -BeExactly (Resolve-Path -Path $Path).Path

Assert-MockCalled Get-Command -Times 1
Assert-MockCalled Start-Process -Times 1
}

Context 'With Nonexistent KoanLocation' {
BeforeAll {
Mock Test-Path { $false }
Mock Update-PSKoan
Mock Get-Command { $false }
Mock Invoke-Item
Mock New-Item
}
It 'opens the file directly when selected editor is unavailable' {
Set-PSKoanSetting -Name Editor -Value "missing_editor"

Show-Karma -Contemplate | Should -BeExactly $TestFile.FullName

It 'should create PSKoans directory' {
Show-Karma -Meditate
Assert-MockCalled Get-Command -Times 1 -ParameterFilter { $Name -eq "missing_editor" }
Assert-MockCalled Invoke-Item -Times 1
}
}

Assert-MockCalled Test-Path -Times 1
Assert-MockCalled Update-PSKoan -Times 1
Assert-MockCalled Get-Command -Times 1
Assert-MockCalled New-Item -Times 1
Assert-MockCalled Invoke-Item -Times 1
Context 'With -Library Switch' {
BeforeAll {
Mock Get-Command { $true } -ParameterFilter { $Name -ne "missing_editor" }
Mock Get-Command { $false } -ParameterFilter { $Name -eq "missing_editor" }
Mock Start-Process {
@{ Editor = $FilePath; Arguments = $ArgumentList }
}
Mock Invoke-Item { $Path }
}

It 'invokes VS Code with "code" set as Editor with proper arguments' {
Set-PSKoanSetting -Name Editor -Value 'code'
$Result = Show-Karma -Library

$Result.Editor | Should -BeExactly 'code'

# Resolve-Path doesn't like embedded quotes
$Path = $Result.Arguments -replace '"'
$Path | Should -BeExactly (Resolve-Path -Path $Path).Path

Assert-MockCalled Get-Command -Times 1
Assert-MockCalled Start-Process -Times 1
}

It 'invokes the set editor with unknown editor chosen' {
Set-PSKoanSetting -Name Editor -Value 'vim'

$Result = Show-Karma -Library
$Result.Editor | Should -BeExactly 'vim'

# Resolve-Path doesn't like embedded quotes
$Path = $Result.Arguments -replace '"'
$Path | Should -BeExactly (Resolve-Path -Path $Path).Path

Assert-MockCalled Get-Command -Times 1
Assert-MockCalled Start-Process -Times 1
}

It 'opens the file directly when selected editor is unavailable' {
Set-PSKoanSetting -Name Editor -Value "missing_editor"

Show-Karma -Library | Should -BeExactly (Get-PSKoanLocation)

Assert-MockCalled Get-Command -Times 1 -ParameterFilter { $Name -eq "missing_editor" }
Assert-MockCalled Invoke-Item -Times 1
}
}

}
}

0 comments on commit c450201

Please sign in to comment.