@@ -11,80 +11,120 @@ Describe 'Microsoft.Windows/FeatureOnDemandList - set operation' -Skip:(!$IsWind
1111 }
1212 }
1313
14+ BeforeAll {
15+ # Dynamically discover capability names instead of hardcoding
16+ $dismOutput = & dism / Online / Get-Capabilities / Format:Table / English 2>&1
17+ if ($LASTEXITCODE -ne 0 ) {
18+ throw " Failed to get capabilities using dism: $dismOutput "
19+ }
20+ $installedMatches = $dismOutput | Select-String - Pattern ' ^\s*(\S+)\s+\|\s+Installed\s*$'
21+ $notPresentMatches = $dismOutput | Select-String - Pattern ' ^\s*(\S+)\s+\|\s+Not Present\s*$'
22+ if (-not $installedMatches -or -not $notPresentMatches ) {
23+ throw " Failed to find both installed and not-present capabilities in DISM output.`n Output:`n $dismOutput "
24+ }
25+ $knownInstalledCapability = $installedMatches [0 ].Matches[0 ].Groups[1 ].Value
26+ $knownNotPresentCapability = $notPresentMatches [0 ].Matches[0 ].Groups[1 ].Value
27+
28+ # Record initial states for cleanup
29+ $script :initialInstalledState = ' Installed'
30+ $script :initialNotPresentState = ' NotPresent'
31+ }
32+
33+ AfterAll {
34+ # Restore capabilities to their original states
35+ if ($knownInstalledCapability ) {
36+ $restoreJson = ' {"capabilities":[{"name":"' + $knownInstalledCapability + ' ","state":"' + $script :initialInstalledState + ' "}]}'
37+ dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $restoreJson 2>&1 | Out-Null
38+ }
39+ if ($knownNotPresentCapability ) {
40+ $restoreJson = ' {"capabilities":[{"name":"' + $knownNotPresentCapability + ' ","state":"' + $script :initialNotPresentState + ' "}]}'
41+ dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $restoreJson 2>&1 | Out-Null
42+ }
43+ }
44+
1445 It ' returns error when name is missing' - Skip:(! $isElevated ) {
1546 $inputJson = ' {"capabilities":[{"state":"Installed"}]}'
1647 $testError = & { dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson 2>&1 }
1748 $LASTEXITCODE | Should -Not - Be 0
49+ " $testError " | Should -Match ' name is required'
1850 }
1951
2052 It ' returns error when state is missing' - Skip:(! $isElevated ) {
21- $inputJson = ' {"capabilities":[{"name":"Language.Basic~~~en-US~0.0.1.0 "}]}'
53+ $inputJson = ' {"capabilities":[{"name":"' + $knownInstalledCapability + ' "}]}'
2254 $testError = & { dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson 2>&1 }
2355 $LASTEXITCODE | Should -Not - Be 0
56+ " $testError " | Should -Match ' state is required'
2457 }
2558
2659 It ' returns error when capabilities array is empty' - Skip:(! $isElevated ) {
2760 $inputJson = ' {"capabilities":[]}'
2861 $testError = & { dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson 2>&1 }
2962 $LASTEXITCODE | Should -Not - Be 0
63+ " $testError " | Should -Match ' cannot be empty'
3064 }
3165
3266 It ' returns error for unsupported desired state' - Skip:(! $isElevated ) {
33- $inputJson = ' {"capabilities":[{"name":"Language.Basic~~~en-US~0.0.1.0","state":"Staged"}]}'
67+ $inputJson = ' {"capabilities":[{"name":"' + $knownInstalledCapability + ' ","state":"Staged"}]}'
68+ $testError = & { dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson 2>&1 }
69+ $LASTEXITCODE | Should -Not - Be 0
70+ " $testError " | Should -Match ' Unsupported desired state'
71+ }
72+
73+ It ' returns error for malformed JSON input' - Skip:(! $isElevated ) {
74+ $inputJson = ' {"capabilities":[{invalid'
75+ $testError = & { dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson 2>&1 }
76+ $LASTEXITCODE | Should -Not - Be 0
77+ }
78+
79+ It ' returns error when installing a non-existent capability' - Skip:(! $isElevated ) {
80+ $inputJson = ' {"capabilities":[{"name":"NonExistent-Capability-1234567890","state":"Installed"}]}'
3481 $testError = & { dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson 2>&1 }
3582 $LASTEXITCODE | Should -Not - Be 0
83+ " $testError " | Should -Match ' not found'
3684 }
3785
38- It ' can install a capability and returns updated state' - Skip:(! $isElevated ) {
39- # Use a capability known to exist on most Windows systems
40- $inputJson = ' {"capabilities":[{"name":"Language.Basic~~~en-US~0.0.1.0","state":"Installed"}]}'
86+ It ' can install a capability and returns updated state' - Skip:(! $isElevated ) - Tag ' Mutating' {
87+ $inputJson = ' {"capabilities":[{"name":"' + $knownInstalledCapability + ' ","state":"Installed"}]}'
4188 $output = dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson | ConvertFrom-Json
4289 $LASTEXITCODE | Should - Be 0
4390 $output.afterState.capabilities | Should -Not - BeNullOrEmpty
4491 $output.afterState.capabilities.Count | Should - Be 1
4592 $cap = $output.afterState.capabilities [0 ]
46- $cap.name | Should - BeExactly ' Language.Basic~~~en-US~0.0.1.0 '
93+ $cap.name | Should - BeExactly $knownInstalledCapability
4794 $cap.state | Should - BeIn @ (' Installed' , ' InstallPending' )
4895 $cap.displayName | Should -Not - BeNullOrEmpty
4996 }
5097
51- It ' can remove a capability and returns updated state' - Skip:(! $isElevated ) {
52- $inputJson = ' {"capabilities":[{"name":"Language.Basic~~~en-US~0.0.1.0 ","state":"NotPresent"}]}'
98+ It ' can remove a capability and returns updated state' - Skip:(! $isElevated ) - Tag ' Mutating ' {
99+ $inputJson = ' {"capabilities":[{"name":"' + $knownNotPresentCapability + ' ","state":"NotPresent"}]}'
53100 $output = dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $inputJson | ConvertFrom-Json
54101 $LASTEXITCODE | Should - Be 0
55102 $output.afterState.capabilities | Should -Not - BeNullOrEmpty
56103 $output.afterState.capabilities.Count | Should - Be 1
57104 $cap = $output.afterState.capabilities [0 ]
58- $cap.name | Should - BeExactly ' Language.Basic~~~en-US~0.0.1.0'
59- # Installed is accepted because some base capabilities cannot be removed by DISM
60- $cap.state | Should - BeIn @ (' NotPresent' , ' Removed' , ' UninstallPending' , ' Staged' , ' Installed' )
105+ $cap.name | Should - BeExactly $knownNotPresentCapability
106+ $cap.state | Should - BeIn @ (' NotPresent' , ' Removed' , ' UninstallPending' , ' Staged' )
61107 }
62108
63- It ' sets state to Installed for an already installed capability' - Skip:(! $isElevated ) {
64- # First ensure the capability is installed
65- $installJson = ' {"capabilities":[{"name":"Language.Basic~~~en-US~0.0.1.0","state":"Installed"}]}'
66- dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $installJson | Out-Null
67- $LASTEXITCODE | Should - Be 0
68-
69- # Set Installed again — should succeed idempotently
109+ It ' sets state to Installed for an already installed capability' - Skip:(! $isElevated ) - Tag ' Mutating' {
110+ # Set Installed on an already-installed capability — should succeed idempotently
111+ $installJson = ' {"capabilities":[{"name":"' + $knownInstalledCapability + ' ","state":"Installed"}]}'
70112 $output = dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $installJson | ConvertFrom-Json
71113 $LASTEXITCODE | Should - Be 0
72114 $output.afterState.capabilities | Should -Not - BeNullOrEmpty
73115 $cap = $output.afterState.capabilities [0 ]
74- $cap.name | Should - BeExactly ' Language.Basic~~~en-US~0.0.1.0 '
116+ $cap.name | Should - BeExactly $knownInstalledCapability
75117 $cap.state | Should - Be ' Installed'
76118 }
77119
78- It ' sets state to NotPresent for an already not-present capability' - Skip:(! $isElevated ) {
79- # Use a capability name that does not exist on the system, so it is already NotPresent
80- $notPresentJson = ' {"capabilities":[{"name":"Test.NonExistent.Capability~~~0.0.1.0","state":"NotPresent"}]}'
81-
82- # Set NotPresent — should succeed idempotently since it is already not present
120+ It ' sets state to NotPresent for an already not-present capability' - Skip:(! $isElevated ) - Tag ' Mutating' {
121+ # Set NotPresent on an already not-present capability — should succeed idempotently
122+ $notPresentJson = ' {"capabilities":[{"name":"' + $knownNotPresentCapability + ' ","state":"NotPresent"}]}'
83123 $output = dsc resource set - r Microsoft.Windows/ FeatureOnDemandList - i $notPresentJson | ConvertFrom-Json
84124 $LASTEXITCODE | Should - Be 0
85125 $output.afterState.capabilities | Should -Not - BeNullOrEmpty
86126 $cap = $output.afterState.capabilities [0 ]
87- $cap.name | Should - BeExactly ' Test.NonExistent.Capability~~~0.0.1.0 '
127+ $cap.name | Should - BeExactly $knownNotPresentCapability
88128 $cap.state | Should - BeIn @ (' NotPresent' , ' Removed' , ' Staged' )
89129
90130 # Set NotPresent again — should still succeed idempotently
0 commit comments