Skip to content
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
14 changes: 14 additions & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ Possible values for the `-AutomaticallyWritePowerShellTip` parameter are `Never`
Tips will only be automatically shown in interactive PowerShell sessions.
This prevents them from appearing unexpectedly when running scripts or other automated processes.

#### Do not show the same tips twice

By default, tiPS will cycle through all available tips, so once all tips have been shown it will restart and display them again.
If you prefer to only see tips that haven't been shown before, you can configure tiPS to only show unshown tips by running:

```powershell
Set-TiPSConfiguration -GetPowerShellTipCondition OnlyGetUnshownTips
```

Possible values for the `-GetPowerShellTipCondition` parameter are `CycleThroughTips` (default) and `OnlyGetUnshownTips`.

When `OnlyGetUnshownTips` is used, tiPS will only automatically display a tip if there are tips that have not been shown yet.
Once all tips have been shown, no more tips will be displayed until new tips are added (by updating the module).

### ⬆️ Automatic updates

New tips are obtained by updating the tiPS module.
Expand Down
8 changes: 8 additions & 0 deletions src/CSharpClasses/tiPSClasses/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,25 @@ public enum TipRetrievalOrder
Random = 2
}

public enum GetPowerShellTipConditions
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Rename the GetPowerShellTipConditions enum to AllTipsShownBehaviours, rename the CycleThroughTips value to ClearShownTipsList, rename the OnlyGetUnshownTips value to DoNotShowTips, and rename the GetPowerShellTipCondition class property to AllTipsShownBehaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed in commit 73e2c88.

The names are now:

  • Enum: AllTipsShownBehaviours
  • Property: AllTipsShownBehaviour
  • Enum values: ClearShownTipsList and DoNotShowTips

Updated all references across C# files, PowerShell files, tests, and documentation.

{
CycleThroughTips = 0,
OnlyGetUnshownTips = 1
}

public class Configuration
{
public ModuleAutoUpdateCadence AutoUpdateCadence { get; set; }
public WritePowerShellTipCadence AutoWritePowerShellTipCadence { get; set; }
public TipRetrievalOrder TipRetrievalOrder { get; set; }
public GetPowerShellTipConditions GetPowerShellTipCondition { get; set; }

public Configuration()
{
AutoUpdateCadence = ModuleAutoUpdateCadence.Never;
AutoWritePowerShellTipCadence = WritePowerShellTipCadence.Never;
TipRetrievalOrder = TipRetrievalOrder.NewestFirst;
GetPowerShellTipCondition = GetPowerShellTipConditions.CycleThroughTips;
}
}
}
71 changes: 71 additions & 0 deletions src/tiPS/Private/AutomaticWritePowerShellTipFunctions.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ InModuleScope -ModuleName tiPS { # Must use InModuleScope to call private functi
Assert-MockCalled WriteAutomaticPowerShellTip -Times 0 -Exactly
}
}

Context 'When the GetPowerShellTipCondition is OnlyGetUnshownTips' {
It 'Should show a tip when there are unseen tips' {
$config = [tiPS.Configuration]::new()
$config.AutoWritePowerShellTipCadence = [tiPS.WritePowerShellTipCadence]::EverySession
$config.GetPowerShellTipCondition = [tiPS.GetPowerShellTipConditions]::OnlyGetUnshownTips
Mock -CommandName TestIfUnseenTipsExist -MockWith { return $true }

WriteAutomaticPowerShellTipIfNeeded -Config $config

Assert-MockCalled WriteAutomaticPowerShellTip -Times 1 -Exactly
}

It 'Should not show a tip when all tips have been shown' {
$config = [tiPS.Configuration]::new()
$config.AutoWritePowerShellTipCadence = [tiPS.WritePowerShellTipCadence]::EverySession
$config.GetPowerShellTipCondition = [tiPS.GetPowerShellTipConditions]::OnlyGetUnshownTips
Mock -CommandName TestIfUnseenTipsExist -MockWith { return $false }

WriteAutomaticPowerShellTipIfNeeded -Config $config

Assert-MockCalled WriteAutomaticPowerShellTip -Times 0 -Exactly
}
}
}

Describe 'Calling WriteLastAutomaticTipWrittenDate' {
Expand All @@ -164,4 +188,51 @@ InModuleScope -ModuleName tiPS { # Must use InModuleScope to call private functi
$lastAutomaticTipWrittenDate | Should -Be $today
}
}

Describe 'Calling TestIfUnseenTipsExist' {
BeforeEach {
# Use a temp configuration data directory instead of reading/overwriting the current user's configuration.
Mock -CommandName Get-TiPSDataDirectoryPath -MockWith {
[string] $directoryPath = "$TestDrive/tiPS" # Use $TestDrive variable so .NET methods can resolve the path.
if (-not (Test-Path -Path $directoryPath -PathType Container))
{
New-Item -Path $directoryPath -ItemType Directory -Force > $null
}
return $directoryPath
}
}

It 'Should return true when no tips have been shown yet' {
# Ensure the file is empty
ClearTipIdsAlreadyShown

$result = TestIfUnseenTipsExist

$result | Should -Be $true
}

It 'Should return true when some tips have been shown but not all' {
# Get all tips and mark only one as shown
[hashtable] $allTips = ReadAllPowerShellTipsFromJsonFile
[string] $firstTipId = $allTips.Keys | Select-Object -First 1
AppendTipIdToTipIdsAlreadyShown -TipId $firstTipId

$result = TestIfUnseenTipsExist

$result | Should -Be $true
}

It 'Should return false when all tips have been shown' {
# Mark all tips as shown
[hashtable] $allTips = ReadAllPowerShellTipsFromJsonFile
foreach ($tipId in $allTips.Keys)
{
AppendTipIdToTipIdsAlreadyShown -TipId $tipId
}

$result = TestIfUnseenTipsExist

$result | Should -Be $false
}
}
}
34 changes: 34 additions & 0 deletions src/tiPS/Private/AutomaticWritePowerShellTipFunctions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ function WriteAutomaticPowerShellTipIfNeeded
([tiPS.WritePowerShellTipCadence]::Monthly) { $shouldShowTip = $daysSinceLastAutomaticTipWritten -ge 30; break }
}

# If the cadence says we should show a tip, check if we should only show unseen tips
if ($shouldShowTip -and $Config.GetPowerShellTipCondition -eq [tiPS.GetPowerShellTipConditions]::OnlyGetUnshownTips)
{
$shouldShowTip = TestIfUnseenTipsExist
}

if ($shouldShowTip)
{
[bool] $isSessionInteractive = TestPowerShellSessionIsInteractive
Expand Down Expand Up @@ -137,3 +143,31 @@ function GetLastAutomaticTipWrittenDateFilePath
[string] $lastAutomaticTipWrittenDateFilePath = Join-Path -Path $appDataDirectoryPath -ChildPath 'LastAutomaticTipWrittenDate.txt'
return $lastAutomaticTipWrittenDateFilePath
}

function TestIfUnseenTipsExist
{
[CmdletBinding()]
[OutputType([bool])]
Param()

[hashtable] $allTips = ReadAllPowerShellTipsFromJsonFile
[string[]] $tipIdsAlreadyShown = ReadTipIdsAlreadyShownOrDefault

# If no tips have been shown yet, there are definitely unseen tips
if ($tipIdsAlreadyShown.Count -eq 0)
{
return $true
}

# Check if there are any tips that haven't been shown yet
foreach ($tipId in $allTips.Keys)
{
if ($tipId -notin $tipIdsAlreadyShown)
{
return $true
}
}

# All tips have been shown
return $false
}
22 changes: 22 additions & 0 deletions src/tiPS/Public/Set-TiPSConfiguration.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ function Set-TiPSConfiguration
Whether to automatically write a PowerShell tip at session startup.
Valid values are Never, EverySession, Daily, Weekly, Biweekly, and Monthly. Default is Never.

.PARAMETER GetPowerShellTipCondition
Controls how tips are selected when automatically showing tips.
Valid values are CycleThroughTips (default) and OnlyGetUnshownTips.
OnlyGetUnshownTips will only show tips that have not been shown before.

.PARAMETER TipRetrievalOrder
The order in which to retrieve PowerShell tips.
Valid values are NewestFirst, OldestFirst, and Random. Default is NewestFirst.
Expand Down Expand Up @@ -60,6 +65,11 @@ function Set-TiPSConfiguration
Set-TiPSConfiguration -TipRetrievalOrder Random

Set the tiPS configuration to retrieve PowerShell tips in random order.

.EXAMPLE
Set-TiPSConfiguration -AutomaticallyWritePowerShellTip Daily -GetPowerShellTipCondition OnlyGetUnshownTips

Set the tiPS configuration to automatically write a PowerShell tip every day, but only if there are tips that have not been shown yet.
#>
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'PartialConfiguration')]
[OutputType([void])]
Expand All @@ -75,6 +85,9 @@ function Set-TiPSConfiguration
[Parameter(Mandatory = $false, ParameterSetName = 'PartialConfiguration', ValueFromPipelineByPropertyName = $true)]
[tiPS.WritePowerShellTipCadence] $AutomaticallyWritePowerShellTip = [tiPS.WritePowerShellTipCadence]::Never,

[Parameter(Mandatory = $false, ParameterSetName = 'PartialConfiguration', ValueFromPipelineByPropertyName = $true)]
[tiPS.GetPowerShellTipConditions] $GetPowerShellTipCondition = [tiPS.GetPowerShellTipConditions]::CycleThroughTips,

[Parameter(Mandatory = $false, ParameterSetName = 'PartialConfiguration', ValueFromPipelineByPropertyName = $true)]
[Alias('TipOrder')]
[tiPS.TipRetrievalOrder] $TipRetrievalOrder = [tiPS.TipRetrievalOrder]::NewestFirst
Expand Down Expand Up @@ -118,6 +131,15 @@ function Set-TiPSConfiguration
}
}

# If the GetPowerShellTipCondition parameter is passed in, set it.
if ($PSBoundParameters.ContainsKey('GetPowerShellTipCondition'))
{
if ($PSCmdlet.ShouldProcess('tiPS configuration GetPowerShellTipCondition property', 'Set'))
{
$script:TiPSConfiguration.GetPowerShellTipCondition = $GetPowerShellTipCondition
}
}

Write-Debug "Saving the tiPS configuration to the configuration file."
WriteConfigurationToFile -Config $script:TiPSConfiguration

Expand Down