Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b90eea2
feat(featureFlag): Include to allow managing feature flags
rulasg Nov 10, 2025
097fede
test(FeatureFlag): ad testing for FF include
rulasg Nov 10, 2025
439e7e8
test(featureFlag): enhance tests for feature flag configuration
rulasg Nov 11, 2025
c36f128
feat(featureFlag): config all FF called
rulasg Nov 11, 2025
b4ad9e5
refactor(config): rename functions and streamline configuration handling
rulasg Nov 11, 2025
21d0795
refactor(dependencies): streamline function renaming and export logic
rulasg Nov 11, 2025
ca575c7
refactor(featureFlag): simplify Save-FeatureFlags function logic
rulasg Nov 11, 2025
e9e3619
refactor(config): replace Rename-Item with Copy-Item for function ali…
rulasg Nov 11, 2025
306a025
refactor(callAPI): make all functions private
rulasg Nov 12, 2025
eaaac3a
fix(callAPI): Allow calling with OutFile
rulasg Nov 12, 2025
2371ddb
refactor(config): update MODULE_NAME assignment for clarity
rulasg Nov 13, 2025
4033351
fix(moduleName): rename functions for consistency
rulasg Nov 13, 2025
48bc4ec
fix(syncIncludeWithModule): add DestinationModulePath parameter to Ad…
rulasg Nov 13, 2025
73233e1
fix(callPrivateContext): ensure ModulePath is used if provided
rulasg Nov 13, 2025
dc8fd03
feat(config): update Mock_Config function to use parameters for paths…
rulasg Nov 13, 2025
33b6f70
feat(featureflag): add module name handling and feature flag manageme…
rulasg Nov 13, 2025
5a084a7
test(featureflag): add tests for registered feature flags and clear d…
rulasg Nov 13, 2025
5a9eaeb
Merge branch 'main' into featureFlag
rulasg Jan 8, 2026
7f02970
Merge branch 'main' into featureFlag
rulasg Jan 11, 2026
8b43268
refactor(tests): rename verbose functions for consistency
rulasg Jan 13, 2026
9d76133
fix(include): correct variable reference for module path
rulasg Jan 13, 2026
46a6bdc
fix(tests): remove loaded module to prevent test interference
rulasg Jan 13, 2026
d8cc355
test(ResolveSourceDestinationPath): refactor tests to use Invoke-Priv…
rulasg Jan 13, 2026
b0159c8
test(featureflag): add tests for feature flag functionality and modul…
rulasg Jan 13, 2026
e8c0282
test(featureflag): enhance tests for feature flag management and cleanup
rulasg Jan 13, 2026
36c6915
Merge remote-tracking branch 'origin/main' into featureFlag
rulasg Jan 13, 2026
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
8 changes: 6 additions & 2 deletions Test/include/callPrivateContext.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ if(-not $MODULE_PATH){ throw "Missing MODULE_PATH variable initialization. Check
function Invoke-PrivateContext {
param (
[Parameter(Mandatory, Position = 0)]
[scriptblock]$ScriptBlock
[scriptblock]$ScriptBlock,
[string]$ModulePath
)

$modulePath = $MODULE_PATH | Split-Path -Parent
if ([string]::IsNullOrEmpty($ModulePath)) {
$modulePath = $MODULE_PATH | Split-Path -Parent
}

$module = Import-Module -Name $modulePath -PassThru

if ($null -eq $module) {
Expand Down
25 changes: 18 additions & 7 deletions Test/include/config.mock.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,40 @@
if(-not $MODULE_NAME){ throw "Missing MODULE_NAME varaible initialization. Check for module.helerp.ps1 file." }

$MOCK_CONFIG_PATH = "test_config_path"
$CONFIG_INVOKE_GET_ROOT_PATH_CMD = "Invoke-$($MODULE_NAME)GetConfigRootPath"
$CONFIG_INVOKE_GET_ROOT_PATH_CMD = "Invoke-{modulename}GetConfigRootPath"

function Mock_Config{
param(
[Parameter(Position=0)][string] $key = "config",
[Parameter(Position=1)][object] $Config
[Parameter(Position=1)][object] $Config,
[Parameter(Position=2)][string] $ModuleName,
[Parameter(Position=3)][string] $MockPath = $MOCK_CONFIG_PATH
)

# Remove mock config path if exists
if(Test-Path $MOCK_CONFIG_PATH){
Remove-Item -Path $MOCK_CONFIG_PATH -ErrorAction SilentlyContinue -Recurse -Force
if(Test-Path $MockPath){
Remove-Item -Path $fullpath -ErrorAction SilentlyContinue -Recurse -Force
}

# create mock config path
New-Item -Path $MOCK_CONFIG_PATH -ItemType Directory -Force
New-Item -Path $MockPath -ItemType Directory -Force

# make full and not relative path
$fullpath = $MockPath | Resolve-Path

# if $config is not null save it to a file
if($null -ne $Config){
$configfile = Join-Path -Path $MOCK_CONFIG_PATH -ChildPath "$key.json"
$configfile = Join-Path -Path $fullpath -ChildPath "$key.json"
$Config | ConvertTo-Json -Depth 10 | Set-Content $configfile
}

if([string]::IsNullOrWhiteSpace($ModuleName)){
$moduleName = $MODULE_NAME
}

$invokefunction = $CONFIG_INVOKE_GET_ROOT_PATH_CMD -replace "{modulename}", $moduleName

# Mock invoke call
MockCallToString $CONFIG_INVOKE_GET_ROOT_PATH_CMD -OutString $MOCK_CONFIG_PATH
MockCallToString $invokefunction -OutString $fullpath

}
69 changes: 38 additions & 31 deletions Test/public/addIncludeToWorkspace.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -233,37 +233,44 @@ $targetPS1 = $moduleRootPath | Join-Path -ChildPath "public\addIncludeToWorkspac

function Test_ResolveSourceDestinationPath{

$DestinationModuleName = "TargetModule"
$SourceModuleName = "SourceModule"
$LocalModuleName = "LocalModule"

$IncludeHelperModulePath = (Get-Module -name Includehelper).Path | Split-Path -parent

New-ModuleV3 -Name $DestinationModuleName ; $DestinationModulePath = $DestinationModuleName | Convert-Path
New-ModuleV3 -Name $SourceModuleName ; $SourceModulePath = $SourceModuleName | Convert-Path
New-ModuleV3 -Name $LocalModuleName ; $LocalModulePath = $LocalModuleName | Convert-Path

$LocalModuleName | Set-Location

# Act Null / Null - Soruce:Include to Destination:local
$resultsource,$resultdestination = Resolve-SourceDestinationPath
Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath

# Act Source / Null - Source: Path to Destination: local
$resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath
Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath

# Act Null / Destination sourceI:Include to Destination: Path
$resultsource,$resultdestination = Resolve-SourceDestinationPath -DestinationModulePath $DestinationModulePath
Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath

# Act Sorce / Destination - Source: Path to Destination: Path
$resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath -DestinationModulePath $DestinationModulePath
Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath
Invoke-PrivateContext {

$DestinationModuleName = "TargetModule"
$SourceModuleName = "SourceModule"
$LocalModuleName = "LocalModule"

# Includehelper root folder
$local = $PSScriptRoot
$IncludeHelperModulePath = $local | Split-Path -Parent | Split-Path -Parent

# TEsting modules
New-ModuleV3 -Name $DestinationModuleName ; $DestinationModulePath = $DestinationModuleName | Convert-Path
New-ModuleV3 -Name $SourceModuleName ; $SourceModulePath = $SourceModuleName | Convert-Path
New-ModuleV3 -Name $LocalModuleName ; $LocalModulePath = $LocalModuleName | Convert-Path

# Set location to test module
$LocalModuleName | Set-Location

# Act Null / Null - Soruce:Include to Destination:local
$resultsource,$resultdestination = Resolve-SourceDestinationPath
Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath

# Act Source / Null - Source: Path to Destination: local
$resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath
Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $LocalModulePath

# Act Null / Destination sourceI:Include to Destination: Path
$resultsource,$resultdestination = Resolve-SourceDestinationPath -DestinationModulePath $DestinationModulePath
Assert-AreEqualPath -Presented $resultsource -Expected $IncludeHelperModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath

# Act Sorce / Destination - Source: Path to Destination: Path
$resultsource,$resultdestination = Resolve-SourceDestinationPath -SourceModulePath $SourceModulePath -DestinationModulePath $DestinationModulePath
Assert-AreEqualPath -Presented $resultsource -Expected $SourceModulePath
Assert-AreEqualPath -Presented $resultdestination -Expected $DestinationModulePath
}

}

Expand Down
14 changes: 13 additions & 1 deletion Test/public/config.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,21 @@ function Test_ConfigInclude{

Set-IncludeHelperConfigValue -Name "config_name" -Value "test_config_value"

# Add Value String
$value = "Some value"
Set-IncludeHelperConfigValue -Name "TestKey" -Value $value
$result = Get-IncludeHelperConfig
Assert-AreEqual -Expected $value -Presented $result.TestKey

Assert-AreEqual -Expected "test_config_value" -Presented $result.config_name
# Add Value Hashtable
$htable = @{ Key1 = "Value1"; Key2 = "Value2" }
Set-IncludeHelperConfigValue -Name "TestHashtable" -Value $htable
$result = Get-IncludeHelperConfig
Assert-AreEqual -Expected $htable.Key1 -Presented $result.TestHashtable.Key1
Assert-AreEqual -Expected $htable.Key2 -Presented $result.TestHashtable.Key2

# Previuse value still there
Assert-AreEqual -Expected $value -Presented $result.TestKey

}

20 changes: 10 additions & 10 deletions Test/public/dependencies.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ function Test_ImportDepepency_Already_loaded{
Mock_ImportModule -Name $name -Folder $modulesFolder

#Act
Set-IncludeHelperVerbose
Enable-IncludeHelperVerbose
Start-MyTranscript
$result = Import-Dependency -Name $name -Verbose -Confirm:$false
$tt = Stop-MyTranscript
Clear-IncludeHelperVerbose
Disable-IncludeHelperVerbose

#Assert verbose message
Assert-AreEqual -Expected $name -Presented $result.Name
Expand All @@ -42,11 +42,11 @@ function Test_ImportDepepency_SideBySide{
Mock_ImportModule -Name $name -Folder $modulesFolder

# Act
Set-IncludeHelperVerbose
Enable-IncludeHelperVerbose
Start-MyTranscript
$result = Import-Dependency -Name $name -Verbose -Confirm:$false
$tt = Stop-MyTranscript
Clear-IncludeHelperVerbose
Disable-IncludeHelperVerbose

# Assert module output
Assert-AreEqual -Expected $name -Presented $result.Name
Expand Down Expand Up @@ -77,11 +77,11 @@ function Test_ImportDepepency_Import_From_Module_Manager{


#Act
Set-IncludeHelperVerbose
Enable-IncludeHelperVerbose
Start-MyTranscript
$output = Import-Dependency -Name $name -Verbose -Confirm:$false
$result = Stop-MyTranscript
Clear-IncludeHelperVerbose
Disable-IncludeHelperVerbose

#Assert verbose message
Assert-AreEqual -Expected $name -Presented $output.Name
Expand Down Expand Up @@ -119,11 +119,11 @@ function Test_ImportDepepency_Install_From_Gallery{
MockCallExpression -Command "Install-Module -Name $name -AllowPrerelease -Force" -Expression $expression

#Act
Set-IncludeHelperVerbose
Enable-IncludeHelperVerbose
Start-MyTranscript
$output = Import-Dependency -Name $name -Verbose -Confirm:$false
$result = Stop-MyTranscript
Clear-IncludeHelperVerbose
Disable-IncludeHelperVerbose

#Assert verbose message
Assert-AreEqual -Expected $name -Presented $output.Name
Expand Down Expand Up @@ -154,11 +154,11 @@ function Test_ImportDependency_Clone_From_GitHub{
Mock_ImportModule -Name $name -Folder $modulesFolder


Set-IncludeHelperVerbose
Enable-IncludeHelperVerbose
Start-MyTranscript
$output = Import-Dependency -Name $name -Verbose -Confirm:$false
$result = Stop-MyTranscript
Clear-IncludeHelperVerbose
Disable-IncludeHelperVerbose

#Assert verbose message
Assert-AreEqual -Expected $name -Presented $output.Name
Expand Down
140 changes: 140 additions & 0 deletions Test/public/featureflag.test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
function Test_FeatureFlag_Success{
Mock_Config

Invoke-PrivateContext{

$ffName = "ff1"
$configFilePath = Invoke-MyCommand -Command "Invoke-IncludeHelperGetConfigRootPath" | Join-Path -ChildPath "config.json"

$result = Test-FeatureFlag -Key $ffName
Assert-IsFalse -Condition $result

# Calling Test-FeatureFlag will create entry on config.FeatureFlags
$config = Get-Content $configFilePath | ConvertFrom-Json -AsHashtable
Assert-IsFalse -Condition $config.FeatureFlags.$ffName

Set-FeatureFlag $ffName
$result = Test-FeatureFlag -Key $ffName
Assert-IsTrue -Condition $result

# Set flag adds $true to the config.FeatureFlags
$config = Get-Content $configFilePath| ConvertFrom-Json -AsHashtable
Assert-IsTrue -Condition $config.FeatureFlags.$ffName

Clear-FeatureFlag $ffName
$result = tff $ffName
Assert-IsFalse -Condition $result

# Clear flag sets the flag to $false in config.FeatureFlags
$config = Get-Content $configFilePath| ConvertFrom-Json -AsHashtable
Assert-IsFalse -Condition $config.FeatureFlags.$ffName
}
}

function Test_RegisteredFeatureFlags_Success{

$modulename = "kk"

# Create Module
New-ModuleV3 -Name $modulename
$fullpath = $modulename | Resolve-Path

# update module with required code to run featureflags in it
Sync-IncludeWithModule -DestinationModulePath $fullpath
Get-IncludeFile invokeCommand.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile MyWrite.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile config.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile featureflag.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile module.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath

# Add a fake Registered featureflags configuration
$reg = @{
deprecated = @(
'ff1'
'ff2'
)
}
$reg | ConvertTo-Json | Out-File -FilePath $fullPath/featureflags.json

# Import module
Import-Module -Name $fullpath
# Mock config for module kk
Mock_Config -ModuleName $modulename -MockPath "kk_config"

# Set feature flags in the kk config
Set-kkFeatureFlag ff1
Set-kkFeatureFlag ff2 -Value $false
Set-kkFeatureFlag ff3

# Assert confirm that all 3 flags are set
$result = Get-kkFeatureFlags
Assert-Count -Expected 3 -Presented $result.Keys
Assert-Contains -Expected "ff1" -Presented $result.Keys
Assert-Contains -Expected "ff2" -Presented $result.Keys
Assert-Contains -Expected "ff3" -Presented $result.Keys

# Act - Clear registered deprecated featureflags from config
Invoke-PrivateContext -ModulePath $fullpath {
Clear-FeatureFlagsRegistered
}

# Assert confirm that deprecated flags are removed and ff3 remains
$result = Get-kkFeatureFlags

Assert-Count -Expected 1 -Presented $result.Keys
Assert-Contains -Expected "ff3" -Presented $result.Keys

# Not sure why but if we leave kk loaded it may interfere with other tests
# In particular when calling Resolve-SourceDestinationPath, that calls Get-ModuleRootPath, it will resolve to kk module.helper.ps1 code and not IncludeHelper module one
# resolving to the kk module path and not IncludeHelper module path.
Remove-Module -Name $modulename -Force
}

function Test_RegisteredFeatureFlags__FFFunction_Success{

$modulename = "kk"

# Mock config for module kk
Mock_Config -ModuleName $modulename -MockPath "kk_config"

# Create Module
New-ModuleV3 -Name $modulename
$fullpath = $modulename | Resolve-Path

# update module with required code to run featureflags in it
Sync-IncludeWithModule -DestinationModulePath $fullpath
Get-IncludeFile invokeCommand.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile MyWrite.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile config.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile featureflag.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath
Get-IncludeFile module.helper.ps1 | Add-IncludeToWorkspace -DestinationModulePath $fullpath

$functioncode = @"

function Get-kkString {
if(TFF ff){
return "ff"
} else {
return "kk"
}
} Export-ModuleMember -Function Get-kkString

"@

$functioncode | Out-File -FilePath ./kk/public/getString.ps1

# Import module
Import-Module -Name $fullpath

Set-kkFeatureFlag ff
$result = Get-kkFeatureFlags
Assert-IsTrue -Condition $result.ff

$result = Get-kkString
Assert-AreEqual -Expected "ff" -Presented $result

# Not sure why but if we leave kk loaded it may interfere with other tests
# In particular when calling Resolve-SourceDestinationPath, that calls Get-ModuleRootPath, it will resolve to kk module.helper.ps1 code and not IncludeHelper module one
# resolving to the kk module path and not IncludeHelper module path.
Remove-Module -Name $modulename -Force
}
Loading
Loading