Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ PVM (PHP Version Manager) is a lightweight PowerShell tool for Windows that make
- [Aliases](#command-aliases)
- [Build Types](#build-types)
- [Namespaced Commands](#namespaced-commands)
- [Scripts](#scripts)
- [Data Storage](#data-storage)
- [Running Tests](#running-tests)
- [Requirements](#requirements-1)
Expand Down Expand Up @@ -378,6 +379,37 @@ pvm cache <subcommand>
pvm cache:<subcommand>
```

### Scripts

PVM includes predefined scripts for common test scenarios, similar to npm scripts in package.json or composer scripts in composer.json. These scripts provide shortcuts for running tests with specific configurations without typing all the options each time.

```sh
# Run a specific script
pvm run <script-name>

# Examples:
pvm run test # ............... Runs all tests with default settings
pvm run test:quiet # ......... Runs tests with verbosity set to None
pvm run test:cov # ........... Runs tests with 80% coverage target
pvm run test:cov80 # ......... Runs tests with 80% coverage target
pvm run test:cov90 # ......... Runs tests with 90% coverage target
pvm run test:full # .......... Runs tests with coverage and detailed output
```

**Available Scripts:**

| Script Name | Command | Description |
|-------------|---------|-------------|
| `test:quiet` | `pvm test --verbosity=None` | Runs tests with verbosity set to None |
| `test:cov` | `pvm test --coverage=75` | Runs tests with 75% coverage target |
| `test:cov80` | `pvm test --coverage=80` | Runs tests with 80% coverage target |
| `test:cov90` | `pvm test --coverage=90` | Runs tests with 90% coverage target |
| `test:full` | `pvm test --coverage=85 --verbosity=Detailed` | Runs tests with coverage and detailed output |

**Customizing Scripts:**

You can customize scripts by editing the `scripts` section in `src/helpers/config.ps1`. The scripts are defined in the `$PVMConfig.defaults.scripts` hashtable. Add or modify scripts to suit your workflow.

## Data Storage

| Item | Location |
Expand Down
9 changes: 9 additions & 0 deletions src/actions/setup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ function Initialize-PVMFiles {
Write-Host -Object "`nFailed to create aliases list." -ForegroundColor DarkYellow
}

$codes += $code = Set-Scripts-List
if ($code -eq 0) {
Write-Host -Object "`nScripts list created successfully at '$($PVMConfig.paths.scriptsList)'." -ForegroundColor DarkGreen
Write-Host -Object "- Use 'pvm scripts' to see available scripts." -ForegroundColor Gray
Write-Host -Object "- Feel free to modify it." -ForegroundColor Gray
} else {
Write-Host -Object "`nFailed to create scripts list." -ForegroundColor DarkYellow
}

return $codes
}

Expand Down
50 changes: 50 additions & 0 deletions src/core/handlers.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -505,3 +505,53 @@ function Invoke-Update {
Display-Msg-By-ExitCode -result $result
return $result.code
}

function Invoke-Run {
param ($arguments)

$scriptName = $arguments[0]
$scripts = Get-Scripts

if ([string]::IsNullOrWhiteSpace($scriptName)) {
Write-Host -Object "`nPlease provide a script name to run: pvm run <script-name>" -ForegroundColor Yellow
Write-Host -Object "`nAvailable scripts:`n" -ForegroundColor Cyan

$maxNameLength = ($scripts.Keys | Measure-Object -Maximum Length).Maximum + ($PVMConfig.env.MIN_PAD_RIGHT_LENGTH * 2)
$scripts.Keys | ForEach-Object {
$name = "$_ ".PadRight($maxNameLength, '.')
$command = $scripts[$_]
Write-Host -Object " $name $command"
}
return -1
}

if (-not $scripts.Contains($scriptName)) {
Write-Host -Object "`nScript '$scriptName' not found." -ForegroundColor Yellow
Write-Host -Object "`nAvailable scripts:`n" -ForegroundColor Cyan
$maxNameLength = ($scripts.Keys | Measure-Object -Maximum Length).Maximum + ($PVMConfig.env.MIN_PAD_RIGHT_LENGTH * 2)
$scripts.Keys | ForEach-Object {
$name = "$_ ".PadRight($maxNameLength, '.')
$command = $scripts[$_]
Write-Host -Object " $name $command"
}
return -1
}

$scriptCommand = $scripts[$scriptName]
Write-Host -Object "`nRunning script: $scriptName" -ForegroundColor Cyan
Write-Host -Object "Command: pvm $scriptCommand`n" -ForegroundColor Gray

$parts = $scriptCommand -split ' '
$command = $parts[0]
$scriptArgs = if ($parts.Count -gt 1) { $parts[1..($parts.Count - 1)] } else { @() }

$actions = Get-Actions -arguments $scriptArgs

if (-not $actions.Contains($command)) {
Write-Host -Object "`nInvalid command in script: $command" -ForegroundColor Yellow
return -1
}

$result = $($actions[$command].action.Invoke())
return $result
}
19 changes: 19 additions & 0 deletions src/core/router.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -350,5 +350,24 @@ function Get-Actions {
}
action = { return Invoke-Update -arguments $script:arguments }
}
'run' = @{
command = 'pvm run <script-name>';
description = 'Run a predefined script from the scripts configuration.';
usage = [ordered]@{
USAGE = 'pvm run <script-name>'
DESCRIPTION = @(
'Runs a predefined script from the scripts configuration.',
'Scripts are shortcuts for common commands with predefined options.'
)
EXAMPLES = @(
'pvm run test:quiet ......... Runs tests with verbosity set to None'
'pvm run test:cov ........... Runs tests with 75% coverage target'
'pvm run test:cov80 ......... Runs tests with 80% coverage target'
'pvm run test:cov90 ......... Runs tests with 90% coverage target'
'pvm run test:full .......... Runs tests with coverage and detailed output'
)
}
action = { return Invoke-Run -arguments $script:arguments }
}
}
}
38 changes: 37 additions & 1 deletion src/helpers/config.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,35 @@ function Get-FlagMap {
return $PVMConfig.defaults.flags
}

function Set-Scripts-List {
try {
$jsonContent = $PVMConfig.defaults.scripts | ConvertTo-Json -Depth 10
Set-Content -Path $PVMConfig.paths.scriptsList -Value $jsonContent -Encoding UTF8

return 0
} catch {
$null = Log-Data -data @{ header = "$($MyInvocation.MyCommand.Name) - Failed to create scripts list"; exception = $_ }
return -1
}
}

function Get-Scripts {
try {
if (Is-File-Exists -path $PVMConfig.paths.scriptsList) {
$data = (Get-Content -Path $PVMConfig.paths.scriptsList -Raw | ConvertFrom-Json)
if ($null -ne $data) {
$ordered = [ordered]@{}
$data.PSObject.Properties | ForEach-Object { $ordered[$_.Name] = $_.Value }
if ($ordered.Count -gt 0) { return $ordered }
}
}
} catch {
$null = Log-Data -data @{ header = "$($MyInvocation.MyCommand.Name) - Failed to get scripts list"; exception = $_ }
}

return $PVMConfig.defaults.scripts
}

function Get-Config {
param([string] $rootPath)

Expand Down Expand Up @@ -104,6 +133,7 @@ function Get-Config {
profileTemplate = "$templates\profile-template.json"
zendExtensionsList = "$templates\zend_extensions.json"
aliasesList = "$templates\aliases.json"
scriptsList = "$templates\scripts.json"
log = $logs
logError = "$logs\error.log"
pathVarBackup = "$logs\path.bak.log"
Expand Down Expand Up @@ -157,7 +187,6 @@ function Get-Config {
'a' = 'add'; '+' = 'add'; 'rm' = 'remove'; '-' = 'remove'
'del' = 'delete'; 'cls' = 'clear'
'logs' = 'log'; 'upgrade' = 'update'
'run' = 'test'
'fix' = 'repair';
}
flags = [ordered]@{
Expand All @@ -166,6 +195,13 @@ function Get-Config {
'--help' = 'help'
'-h' = 'help'
}
scripts = [ordered]@{
'test:quiet' = 'test --verbosity=None'
'test:cov' = 'test --coverage=75'
'test:cov80' = 'test --coverage=80'
'test:cov90' = 'test --coverage=90'
'test:full' = 'test --coverage=85 --verbosity=Detailed --sort=coverage --group=folder'
}
}
}
}
7 changes: 7 additions & 0 deletions tests/actions/setup.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ Describe "Initialize-PVMFiles" {
Mock Create-Profile-Template { return 0 }
Mock Set-Zend-Extensions-List { return 0 }
Mock Set-Aliases-List { return 0 }
Mock Set-Scripts-List { return 0 }
}

It "Returns -1 when the example profile creation fails" {
Expand All @@ -250,6 +251,12 @@ Describe "Initialize-PVMFiles" {
$result = Setup-Environment-Directories-And-Files
$result | Should -Be -1
}

It "Returns -1 when the scripts file creation fails" {
Mock Set-Scripts-List { return -1 }
$result = Setup-Environment-Directories-And-Files
$result | Should -Be -1
}
}

Describe "Setup-Environment-Directories-And-Files" {
Expand Down
40 changes: 40 additions & 0 deletions tests/core/handlers.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1443,3 +1443,43 @@ Describe "Invoke-Update Tests" {
Should -Invoke Update-PVM -Times 1
}
}

Describe "Invoke-Run Tests" {
BeforeAll {
Mock Get-Actions {
[ordered]@{
'install' = @{ action = { return 0 } }
'list' = @{ action = { return 0 } }
'ini' = @{ action = { return 0 } }
'cache' = @{ action = { return 0 } }
'test' = @{ action = { return 0 } }
}
}
}

It "Should return -1 when no arguments are provided" {
$result = Invoke-Run -arguments @()
$result | Should -Be -1
}

It "Should return -1 when an unknown script is provided" {
Mock Get-Scripts { return @{ 'script1' = 'command1'; 'script2' = 'command2' } }

$result = Invoke-Run -arguments @('unknown')
$result | Should -Be -1
}

It "Should return -1 when an unknown command is provided" {
Mock Get-Scripts { return @{ 'cmd1:arg1' = 'command1'; 'cmd2:arg2' = 'command2' } }

$result = Invoke-Run -arguments @('cmd1:arg1')
$result | Should -Be -1
}

It "Should return 0 when a valid script is provided" {
Mock Get-Scripts { return @{ 'test:cov' = 'test --coverage'; 'test:quiet' = 'test --verbosity=None' } }

$result = Invoke-Run -arguments @('test:cov')
$result | Should -Be 0
}
}
9 changes: 9 additions & 0 deletions tests/core/router.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Describe "Get-Actions Tests" {
Mock Invoke-Cache { }
Mock Invoke-Aliases { }
Mock Invoke-Update { }
Mock Invoke-Run { }
}

It "Should return ordered hashtable with all actions" {
Expand All @@ -44,6 +45,7 @@ Describe "Get-Actions Tests" {
$actions.Keys | Should -Contain 'test'
$actions.Keys | Should -Contain 'log'
$actions.Keys | Should -Contain 'update'
$actions.Keys | Should -Contain 'run'
}

It "Should set script-level arguments variable" {
Expand Down Expand Up @@ -174,6 +176,13 @@ Describe "Get-Actions Tests" {

Should -Invoke Invoke-Update -Times 1
}

It "Should execute run action" {
$actions = Get-Actions -arguments @()
$actions['run'].action.Invoke()

Should -Invoke Invoke-Run -Times 1
}
}
}

Expand Down
56 changes: 55 additions & 1 deletion tests/helpers/config.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Describe "Set-Aliases-List" {
Describe "Get-Aliases" {
BeforeAll {
New-Item -ItemType Directory -Force -Path $TEMPLATES_PATH | Out-Null
$testContent = [ordered]@{'?' = 'help'; 'i' = 'install'; 'init' = 'setup'}
$testContent = [ordered]@{'?' = 'help'; 'i' = 'install'; 'init' = 'setup'}
$testContent | ConvertTo-Json -Depth 10 | Set-Content -Path $ALIASES_LIST_PATH
$script:DEFAULT_ALIASES = $PVMConfig.defaults.aliases
}
Expand Down Expand Up @@ -222,6 +222,60 @@ Describe "Get-FlagMap" {
}
}

Describe "Set-Scripts-List" {
BeforeAll {
$script:TEMPLATES_PATH = $PVMConfig.paths.templates = 'TestDrive:\\storage\data\templates'
$PVMConfig.paths.scriptsList = "$TEMPLATES_PATH\scripts.json"
New-Item -ItemType Directory -Force -Path $script:TEMPLATES_PATH | Out-Null
$script:DEFAULT_SCRIPTS = $PVMConfig.defaults.scripts
}

It "Creates scripts.json" {
$result = Set-Scripts-List
$result | Should -Be 0

$result = Get-Scripts
$result.Count | Should -Be $DEFAULT_SCRIPTS.Count
}

It "Returns -1 when exception is thrown" {
Mock Set-Content { throw 'Test exception' }
$result = Set-Scripts-List
$result | Should -Be -1
}
}

Describe "Get-Scripts" {
BeforeAll {
$script:TEMPLATES_PATH = $PVMConfig.paths.templates = 'TestDrive:\\storage\data\templates'
$script:SCRIPTS_LIST_PATH = $PVMConfig.paths.scriptsList = "$TEMPLATES_PATH\scripts.json"
New-Item -ItemType Directory -Path $script:TEMPLATES_PATH | Out-Null
$testContent = [ordered]@{'test:quiet' = 'test --verbosity=None'; 'test:cov' = 'test --coverage=75'}
$testContent | ConvertTo-Json -Depth 10 | Set-Content -Path $SCRIPTS_LIST_PATH
$script:DEFAULT_SCRIPTS = $PVMConfig.defaults.scripts
}

It "Returns scripts from scripts.json or PVMConfig.defaults.scripts" {
$result = Get-Scripts
$result.Count | Should -Be 2
$result['test:quiet'] | Should -Be 'test --verbosity=None'
$result['test:cov'] | Should -Be 'test --coverage=75'
}

It "Falls back to DEFAULT_SCRIPTS value" {
Remove-Item -Path "$script:TEMPLATES_PATH\scripts.json"
$result = Get-Scripts
$result.Count | Should -Be $DEFAULT_SCRIPTS.Count
}

It "Returns default value when exception is thrown" {
Mock Is-File-Exists { return $true }
Mock Get-Content { throw 'Test exception' }
$result = Get-Scripts
$result.Count | Should -Be $DEFAULT_SCRIPTS.Count
}
}

Describe "Get-Config" {
Context "When .env file exists" {
BeforeAll {
Expand Down