Skip to content

Commit 6d1b5fd

Browse files
committed
#215 feat: enhance Set-NovaUpdateNotificationPreference with WhatIf support and improved messaging
refactor(Set-NovaUpdateNotificationPreference): align with terminal-ux-design principles Fixes #226
1 parent ea1763c commit 6d1b5fd

10 files changed

Lines changed: 247 additions & 30 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
2828
- `Invoke-NovaRelease` now shows progress for the main release phases, ends with the publish target plus a next-step hint, and uses a plan summary instead of a success summary when `-WhatIf` previews the release.
2929
- `New-NovaModulePackage` now shows progress for build validation and artifact creation, ends with the package target plus the next suggested deployment step, and uses a package-plan summary in `-WhatIf` mode.
3030
- `Publish-NovaModule` now shows progress for build validation, publish, local import, and CI restore phases, ends with the publish target plus a suggested verification step, and uses a publish-plan summary in `-WhatIf` mode.
31+
- `Set-NovaUpdateNotificationPreference` now ends with a clear success or preview summary, prints the settings file path, suggests `Get-NovaUpdateNotificationPreference` as the next verification step, and gives a more actionable validation error when no enable/disable switch is supplied.
3132

3233
### Deprecated
3334

RELEASE_NOTE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ This file summarizes the release notes for NovaModuleTools. **UNRELEASED** chang
2424
- `Invoke-NovaRelease` now shows progress for the main release phases, ends with the publish target plus a next-step hint, and uses a plan summary instead of a success summary when `-WhatIf` previews the release.
2525
- `New-NovaModulePackage` now shows progress for build validation and artifact creation, ends with the package target plus the next suggested deployment step, and uses a package-plan summary in `-WhatIf` mode.
2626
- `Publish-NovaModule` now shows progress for build validation, publish, local import, and CI restore phases, ends with the publish target plus a suggested verification step, and uses a publish-plan summary in `-WhatIf` mode.
27+
- `Set-NovaUpdateNotificationPreference` now ends with a clear success or preview summary, prints the settings file path, suggests `Get-NovaUpdateNotificationPreference` as the next verification step, and gives a more actionable validation error when no enable/disable switch is supplied.
2728

2829
### Deprecated
2930

docs/NovaModuleTools/en-US/Set-NovaUpdateNotificationPreference.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ The same stored preference is also used by `Update-NovaModuleTool` (alias: `Upda
3838

3939
Stable self-updates remain available and do not require prerelease eligibility.
4040

41+
When the preference changes, Nova prints the settings file path together with the next recommended verification command. In `-WhatIf` mode, Nova ends with a preview summary instead of writing the preference file.
42+
4143
## EXAMPLES
4244

4345
### EXAMPLE 1
@@ -46,7 +48,7 @@ Stable self-updates remain available and do not require prerelease eligibility.
4648
PS> Set-NovaUpdateNotificationPreference -DisablePrereleaseNotifications
4749
```
4850

49-
Turns off prerelease self-update eligibility and restricts `Update-NovaModuleTool` to stable releases only.
51+
Turns off prerelease self-update eligibility, keeps stable releases available, and suggests `Get-NovaUpdateNotificationPreference` as the next verification step.
5052

5153
### EXAMPLE 2
5254

@@ -55,15 +57,15 @@ PS> Set-NovaUpdateNotificationPreference -EnablePrereleaseNotifications
5557
```
5658

5759
Turns prerelease self-update eligibility back on, which allows `Update-NovaModuleTool` /
58-
`Update-NovaModuleTools` to consider a prerelease target again.
60+
`Update-NovaModuleTools` to consider a prerelease target again and suggests `Get-NovaUpdateNotificationPreference` as the next verification step.
5961

6062
### EXAMPLE 3
6163

6264
```text
6365
PS> Set-NovaUpdateNotificationPreference -DisablePrereleaseNotifications -WhatIf
6466
```
6567

66-
Previews the change that would disable prerelease self-update eligibility.
68+
Previews the change that would disable prerelease self-update eligibility without writing the settings file.
6769

6870
### EXAMPLE 4
6971

@@ -195,6 +197,8 @@ Returns the current prerelease self-update state, the always-available stable-up
195197

196198
Use this command together with `Get-NovaUpdateNotificationPreference` when you want to confirm the stored setting.
197199

200+
Use `-WhatIf` or `-Confirm` when you want an easy way to preview or stop the change before the settings file is updated.
201+
198202
## RELATED LINKS
199203

200204
- [Get-NovaUpdateNotificationPreference](./Get-NovaUpdateNotificationPreference.md)

src/private/update/GetNovaUpdateNotificationPreferenceChangeContext.ps1

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,27 @@ function Get-NovaUpdateNotificationPreferenceChangeContext {
22
[CmdletBinding()]
33
param(
44
[switch]$EnablePrereleaseNotifications,
5-
[switch]$DisablePrereleaseNotifications
5+
[switch]$DisablePrereleaseNotifications,
6+
[hashtable]$WorkflowParams = @{}
67
)
78

89
if ($EnablePrereleaseNotifications.IsPresent) {
910
return [pscustomobject]@{
1011
PrereleaseNotificationsEnabled = $true
1112
Target = Get-NovaUpdateSettingsFilePath
12-
Action = 'Enable prerelease update notifications'
13+
Action = 'Enable prerelease self-update notifications'
14+
WorkflowParams = $WorkflowParams
1315
}
1416
}
1517

1618
if ($DisablePrereleaseNotifications.IsPresent) {
1719
return [pscustomobject]@{
1820
PrereleaseNotificationsEnabled = $false
1921
Target = Get-NovaUpdateSettingsFilePath
20-
Action = 'Disable prerelease update notifications'
22+
Action = 'Disable prerelease self-update notifications'
23+
WorkflowParams = $WorkflowParams
2124
}
2225
}
2326

24-
Stop-NovaOperation -Message 'Specify either -EnablePrereleaseNotifications or -DisablePrereleaseNotifications.' -ErrorId 'Nova.Validation.UpdateNotificationPreferenceChangeRequired' -Category InvalidArgument -TargetObject 'PrereleaseNotifications'
27+
Stop-NovaOperation -Message 'Specify either -EnablePrereleaseNotifications or -DisablePrereleaseNotifications. Example: Set-NovaUpdateNotificationPreference -DisablePrereleaseNotifications' -ErrorId 'Nova.Validation.UpdateNotificationPreferenceChangeRequired' -Category InvalidArgument -TargetObject 'PrereleaseNotifications'
2528
}
Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,135 @@
11
function Invoke-NovaUpdateNotificationPreferenceChange {
22
[CmdletBinding()]
33
param(
4-
[Parameter(Mandatory)][pscustomobject]$WorkflowContext
4+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
5+
[switch]$ShouldRun
56
)
67

8+
$whatIfEnabled = Test-NovaUpdateNotificationPreferenceChangeWhatIfEnabled -WorkflowContext $WorkflowContext
9+
if (-not $ShouldRun) {
10+
if ($whatIfEnabled) {
11+
Write-NovaUpdateNotificationPreferenceChangeResult -WorkflowContext $WorkflowContext -WhatIfEnabled
12+
}
13+
14+
return
15+
}
16+
717
Write-NovaUpdateNotificationPreference -PrereleaseNotificationsEnabled:$WorkflowContext.PrereleaseNotificationsEnabled
8-
return Get-NovaUpdateNotificationPreferenceStatus
18+
$status = Get-NovaUpdateNotificationPreferenceStatus
19+
Write-NovaUpdateNotificationPreferenceChangeResult -WorkflowContext $WorkflowContext -Status $status
20+
return $status
21+
}
22+
23+
function Test-NovaUpdateNotificationPreferenceChangeWhatIfEnabled {
24+
[CmdletBinding()]
25+
param(
26+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext
27+
)
28+
29+
return $WorkflowContext.WorkflowParams.ContainsKey('WhatIf') -and $WorkflowContext.WorkflowParams.WhatIf
30+
}
31+
32+
function Write-NovaUpdateNotificationPreferenceChangeResult {
33+
[CmdletBinding()]
34+
param(
35+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
36+
[AllowNull()][pscustomobject]$Status,
37+
[switch]$WhatIfEnabled
38+
)
39+
40+
Write-Message (Get-NovaUpdateNotificationPreferenceChangeStatusMessage -WorkflowContext $WorkflowContext -WhatIfEnabled:$WhatIfEnabled) -color Green
41+
Write-Message "Settings file: $( Get-NovaUpdateNotificationPreferenceChangeSettingsPath -WorkflowContext $WorkflowContext -Status $Status )"
42+
Write-Message (Get-NovaUpdateNotificationPreferenceChangeAvailabilityMessage -WhatIfEnabled:$WhatIfEnabled)
43+
44+
foreach ($line in (Get-NovaUpdateNotificationPreferenceChangeNextStepLine -WorkflowContext $WorkflowContext -WhatIfEnabled:$WhatIfEnabled)) {
45+
Write-Message $line
46+
}
47+
}
48+
49+
function Get-NovaUpdateNotificationPreferenceChangeStatusMessage {
50+
[CmdletBinding()]
51+
param(
52+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
53+
[switch]$WhatIfEnabled
54+
)
55+
56+
$stateText = Get-NovaUpdateNotificationPreferenceChangeStateText -PrereleaseNotificationsEnabled:$WorkflowContext.PrereleaseNotificationsEnabled
57+
if ($WhatIfEnabled) {
58+
return "Notification preference plan ready: prerelease self-updates $stateText"
59+
}
60+
61+
return "Prerelease self-updates are now $stateText."
62+
}
63+
64+
function Get-NovaUpdateNotificationPreferenceChangeSettingsPath {
65+
[CmdletBinding()]
66+
param(
67+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
68+
[AllowNull()][pscustomobject]$Status
69+
)
70+
71+
if ($null -ne $Status -and ($Status.PSObject.Properties.Name -contains 'SettingsPath')) {
72+
return $Status.SettingsPath
73+
}
74+
75+
return $WorkflowContext.Target
76+
}
77+
78+
function Get-NovaUpdateNotificationPreferenceChangeAvailabilityMessage {
79+
[CmdletBinding()]
80+
param(
81+
[switch]$WhatIfEnabled
82+
)
83+
84+
if ($WhatIfEnabled) {
85+
return 'Stable self-updates would remain available.'
86+
}
87+
88+
return 'Stable self-updates remain available.'
89+
}
90+
91+
function Get-NovaUpdateNotificationPreferenceChangeNextStepLine {
92+
[CmdletBinding()]
93+
param(
94+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext,
95+
[switch]$WhatIfEnabled
96+
)
97+
98+
if ($WhatIfEnabled) {
99+
return @(
100+
'Next step:'
101+
"Run $( Get-NovaUpdateNotificationPreferenceChangeCommandLine -WorkflowContext $WorkflowContext ) without -WhatIf when you are ready to store the preference."
102+
)
103+
}
104+
105+
return @(
106+
'Next step:'
107+
'Get-NovaUpdateNotificationPreference'
108+
)
109+
}
110+
111+
function Get-NovaUpdateNotificationPreferenceChangeCommandLine {
112+
[CmdletBinding()]
113+
param(
114+
[Parameter(Mandatory)][pscustomobject]$WorkflowContext
115+
)
116+
117+
if ($WorkflowContext.PrereleaseNotificationsEnabled) {
118+
return 'Set-NovaUpdateNotificationPreference -EnablePrereleaseNotifications'
119+
}
120+
121+
return 'Set-NovaUpdateNotificationPreference -DisablePrereleaseNotifications'
122+
}
123+
124+
function Get-NovaUpdateNotificationPreferenceChangeStateText {
125+
[CmdletBinding()]
126+
param(
127+
[Parameter(Mandatory)][bool]$PrereleaseNotificationsEnabled
128+
)
129+
130+
if ($PrereleaseNotificationsEnabled) {
131+
return 'enabled'
132+
}
133+
134+
return 'disabled'
9135
}

src/public/SetNovaUpdateNotificationPreference.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ function Set-NovaUpdateNotificationPreference {
88
[switch]$DisablePrereleaseNotifications
99
)
1010

11-
$workflowContext = Get-NovaUpdateNotificationPreferenceChangeContext -EnablePrereleaseNotifications:$EnablePrereleaseNotifications -DisablePrereleaseNotifications:$DisablePrereleaseNotifications
11+
$workflowContext = Get-NovaUpdateNotificationPreferenceChangeContext -EnablePrereleaseNotifications:$EnablePrereleaseNotifications -DisablePrereleaseNotifications:$DisablePrereleaseNotifications -WorkflowParams @{WhatIf = [bool]$WhatIfPreference}
1212

13-
if (-not $PSCmdlet.ShouldProcess($workflowContext.Target, $workflowContext.Action)) {
13+
$shouldRun = $PSCmdlet.ShouldProcess($workflowContext.Target, $workflowContext.Action)
14+
if (-not $shouldRun -and -not $WhatIfPreference) {
1415
return
1516
}
1617

17-
return Invoke-NovaUpdateNotificationPreferenceChange -WorkflowContext $workflowContext
18+
return Invoke-NovaUpdateNotificationPreferenceChange -WorkflowContext $workflowContext -ShouldRun:$shouldRun
1819
}

tests/private/update/GetNovaUpdateNotificationPreferenceChangeContext.Tests.ps1

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,23 @@ Describe 'Get-NovaUpdateNotificationPreferenceChangeContext' {
1616
}
1717

1818
It 'returns an enable context when -EnablePrereleaseNotifications is set' {
19-
$context = Get-NovaUpdateNotificationPreferenceChangeContext -EnablePrereleaseNotifications
19+
$context = Get-NovaUpdateNotificationPreferenceChangeContext -EnablePrereleaseNotifications -WorkflowParams @{WhatIf = $true}
2020

2121
$context.PrereleaseNotificationsEnabled | Should -BeTrue
22-
$context.Action | Should -Be 'Enable prerelease update notifications'
22+
$context.Action | Should -Be 'Enable prerelease self-update notifications'
2323
$context.Target | Should -Not -BeNullOrEmpty
24+
$context.WorkflowParams | Should -BeOfType Hashtable
25+
$context.WorkflowParams.WhatIf | Should -BeTrue
2426
}
2527

2628
It 'returns a disable context when -DisablePrereleaseNotifications is set' {
2729
$context = Get-NovaUpdateNotificationPreferenceChangeContext -DisablePrereleaseNotifications
2830

2931
$context.PrereleaseNotificationsEnabled | Should -BeFalse
30-
$context.Action | Should -Be 'Disable prerelease update notifications'
32+
$context.Action | Should -Be 'Disable prerelease self-update notifications'
3133
}
3234

3335
It 'throws via Stop-NovaOperation when neither switch is provided' {
34-
{Get-NovaUpdateNotificationPreferenceChangeContext} | Should -Throw '*Specify either*'
36+
{Get-NovaUpdateNotificationPreferenceChangeContext} | Should -Throw '*Example: Set-NovaUpdateNotificationPreference -DisablePrereleaseNotifications*'
3537
}
3638
}

tests/private/update/InvokeNovaUpdateNotificationPreferenceChange.Tests.ps1

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,74 @@ BeforeAll {
44

55
function Write-NovaUpdateNotificationPreference {param([bool]$PrereleaseNotificationsEnabled)}
66
function Get-NovaUpdateNotificationPreferenceStatus {return [pscustomobject]@{PrereleaseNotificationsEnabled = $true; SettingsPath = '/tmp/x.json'}}
7+
function Write-Message {param([string]$Text, [string]$color)}
8+
}
9+
10+
Describe 'Test-NovaUpdateNotificationPreferenceChangeWhatIfEnabled' {
11+
It 'returns true when WorkflowParams.WhatIf is enabled' {
12+
$workflowContext = [pscustomobject]@{WorkflowParams = @{WhatIf = $true}}
13+
Test-NovaUpdateNotificationPreferenceChangeWhatIfEnabled -WorkflowContext $workflowContext | Should -BeTrue
14+
}
15+
16+
It 'returns false when WorkflowParams.WhatIf is not enabled' {
17+
$workflowContext = [pscustomobject]@{WorkflowParams = @{}}
18+
Test-NovaUpdateNotificationPreferenceChangeWhatIfEnabled -WorkflowContext $workflowContext | Should -BeFalse
19+
}
720
}
821

922
Describe 'Invoke-NovaUpdateNotificationPreferenceChange' {
23+
BeforeEach {
24+
Mock Write-Message {}
25+
}
26+
1027
It 'writes the requested preference and returns the resulting status' {
1128
Mock Write-NovaUpdateNotificationPreference {}
1229
Mock Get-NovaUpdateNotificationPreferenceStatus {return [pscustomobject]@{PrereleaseNotificationsEnabled = $false; SettingsPath = '/tmp/x.json'}}
1330

14-
$workflowContext = [pscustomobject]@{PrereleaseNotificationsEnabled = $false; Action = 'Disable prerelease update notifications'; Target = '/tmp/x.json'}
15-
$status = Invoke-NovaUpdateNotificationPreferenceChange -WorkflowContext $workflowContext
31+
$workflowContext = [pscustomobject]@{
32+
PrereleaseNotificationsEnabled = $false
33+
Action = 'Disable prerelease self-update notifications'
34+
Target = '/tmp/x.json'
35+
WorkflowParams = @{}
36+
}
37+
$status = Invoke-NovaUpdateNotificationPreferenceChange -WorkflowContext $workflowContext -ShouldRun
1638

1739
Assert-MockCalled Write-NovaUpdateNotificationPreference -Times 1 -ParameterFilter {
1840
$PrereleaseNotificationsEnabled -eq $false
1941
}
2042
Assert-MockCalled Get-NovaUpdateNotificationPreferenceStatus -Times 1
43+
Assert-MockCalled Write-Message -Times 4
44+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
45+
$Text -eq 'Prerelease self-updates are now disabled.' -and $color -eq 'Green'
46+
}
47+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
48+
$Text -eq 'Get-NovaUpdateNotificationPreference'
49+
}
2150
$status.PrereleaseNotificationsEnabled | Should -BeFalse
2251
}
52+
53+
It 'writes a preview summary in WhatIf mode without storing the preference' {
54+
Mock Write-NovaUpdateNotificationPreference {}
55+
Mock Get-NovaUpdateNotificationPreferenceStatus {}
56+
57+
$workflowContext = [pscustomobject]@{
58+
PrereleaseNotificationsEnabled = $true
59+
Action = 'Enable prerelease self-update notifications'
60+
Target = '/tmp/x.json'
61+
WorkflowParams = @{WhatIf = $true}
62+
}
63+
64+
$status = Invoke-NovaUpdateNotificationPreferenceChange -WorkflowContext $workflowContext
65+
66+
Assert-MockCalled Write-NovaUpdateNotificationPreference -Times 0
67+
Assert-MockCalled Get-NovaUpdateNotificationPreferenceStatus -Times 0
68+
Assert-MockCalled Write-Message -Times 4
69+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
70+
$Text -eq 'Notification preference plan ready: prerelease self-updates enabled' -and $color -eq 'Green'
71+
}
72+
Assert-MockCalled Write-Message -Times 1 -ParameterFilter {
73+
$Text -eq 'Run Set-NovaUpdateNotificationPreference -EnablePrereleaseNotifications without -WhatIf when you are ready to store the preference.'
74+
}
75+
$status | Should -BeNullOrEmpty
76+
}
2377
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function Get-NovaUpdateNotificationPreferenceChangeContext {
2+
param(
3+
[switch]$EnablePrereleaseNotifications,
4+
[switch]$DisablePrereleaseNotifications,
5+
[hashtable]$WorkflowParams
6+
)
7+
8+
$script:ctxArgs = @{
9+
Enable = [bool]$EnablePrereleaseNotifications
10+
Disable = [bool]$DisablePrereleaseNotifications
11+
WhatIf = $WorkflowParams.WhatIf
12+
}
13+
14+
return [pscustomobject]@{
15+
Target = 'nm'
16+
Action = 'Set'
17+
WorkflowParams = $WorkflowParams
18+
}
19+
}
20+
21+
function Invoke-NovaUpdateNotificationPreferenceChange {
22+
param(
23+
$WorkflowContext,
24+
[switch]$ShouldRun
25+
)
26+
27+
$script:invoked = $true
28+
$script:shouldRun = [bool]$ShouldRun
29+
return [pscustomobject]@{Changed = $true}
30+
}

0 commit comments

Comments
 (0)