@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/windows/windows_version_validator.dart';
99import 'package:test/fake.dart' ;
1010
1111import '../src/common.dart' ;
12+ import '../src/context.dart' ;
1213
1314/// Fake [_WindowsUtils] to use for testing
1415class FakeValidOperatingSystemUtils extends Fake
@@ -21,14 +22,22 @@ class FakeValidOperatingSystemUtils extends Fake
2122}
2223
2324class FakeProcessLister extends Fake implements ProcessLister {
24- FakeProcessLister ({required this .result, this .exitCode = 0 });
25+ FakeProcessLister ({
26+ required this .result,
27+ this .exitCode = 0 ,
28+ this .powershellAvailable = true ,
29+ });
2530 final String result;
2631 final int exitCode;
32+ final bool powershellAvailable;
2733
2834 @override
2935 Future <ProcessResult > getProcessesWithPath () async {
3036 return ProcessResult (0 , exitCode, result, null );
3137 }
38+
39+ @override
40+ bool canRunPowershell () => powershellAvailable;
3241}
3342
3443FakeProcessLister ofdRunning () {
@@ -43,6 +52,10 @@ FakeProcessLister failure() {
4352 return FakeProcessLister (result: r'Path: "C:\Program Files\Google\Chrome\Application\chrome.exe' , exitCode: 10 );
4453}
4554
55+ FakeProcessLister powershellUnavailable () {
56+ return FakeProcessLister (result: '' , powershellAvailable: false );
57+ }
58+
4659/// The expected validation result object for
4760/// a passing windows version test
4861const ValidationResult validWindows10ValidationResult = ValidationResult (
@@ -70,6 +83,15 @@ const ValidationResult ofdFoundRunning = ValidationResult(
7083 statusInfo: 'Problem detected with Windows installation' ,
7184);
7285
86+ const ValidationResult powershellUnavailableResult = ValidationResult (
87+ ValidationType .partial,
88+ < ValidationMessage > [
89+ ValidationMessage .hint ('Failed to find ${ProcessLister .powershell } or ${ProcessLister .pwsh } on PATH' ),
90+ ],
91+ statusInfo: 'Problem detected with Windows installation' ,
92+ );
93+
94+
7395const ValidationResult getProcessFailed = ValidationResult (
7496 ValidationType .partial,
7597 < ValidationMessage > [
@@ -158,6 +180,18 @@ OS 版本: 10.0.22621 暂缺 Build 22621
158180 expect (result.messages[0 ].message, ofdFoundRunning.messages[0 ].message, reason: 'The ValidationMessage message should be the same' );
159181 });
160182
183+ testWithoutContext ('Reports missing powershell' , () async {
184+ final WindowsVersionValidator validator =
185+ WindowsVersionValidator (
186+ operatingSystemUtils: FakeValidOperatingSystemUtils (),
187+ processLister: powershellUnavailable ());
188+ final ValidationResult result = await validator.validate ();
189+ expect (result.type, powershellUnavailableResult.type, reason: 'The ValidationResult type should be the same (partial)' );
190+ expect (result.statusInfo, powershellUnavailableResult.statusInfo, reason: 'The ValidationResult statusInfo should be the same' );
191+ expect (result.messages.length, 1 , reason: 'The ValidationResult should have precisely 1 message' );
192+ expect (result.messages[0 ].message, powershellUnavailableResult.messages[0 ].message, reason: 'The ValidationMessage message should be the same' );
193+ });
194+
161195 testWithoutContext ('Reports failure of Get-Process' , () async {
162196 final WindowsVersionValidator validator =
163197 WindowsVersionValidator (
@@ -169,4 +203,75 @@ OS 版本: 10.0.22621 暂缺 Build 22621
169203 expect (result.messages.length, 1 , reason: 'The ValidationResult should have precisely 1 message' );
170204 expect (result.messages[0 ].message, getProcessFailed.messages[0 ].message, reason: 'The ValidationMessage message should be the same' );
171205 });
206+
207+ testWithoutContext ('getProcessesWithPath successfully runs with powershell' , () async {
208+ final ProcessLister processLister = ProcessLister (
209+ FakeProcessManager .list (
210+ < FakeCommand > [
211+ const FakeCommand (
212+ command: < String > [
213+ ProcessLister .powershell,
214+ '-command' ,
215+ 'Get-Process | Format-List Path' ,
216+ ],
217+ stdout: ProcessLister .powershell,
218+ ),
219+ ],
220+ )..excludedExecutables.add (ProcessLister .pwsh),
221+ );
222+
223+ try {
224+ final ProcessResult result = await processLister.getProcessesWithPath ();
225+ expect (result.stdout, ProcessLister .powershell);
226+ // ignore: avoid_catches_without_on_clauses
227+ } catch (e) {
228+ fail ('Unexpected exception: $e ' );
229+ }
230+ });
231+
232+ testWithoutContext ('getProcessesWithPath falls back to pwsh when powershell is not on the path' , () async {
233+ final ProcessLister processLister = ProcessLister (
234+ FakeProcessManager .list (
235+ < FakeCommand > [
236+ const FakeCommand (
237+ command: < String > [
238+ ProcessLister .pwsh,
239+ '-command' ,
240+ 'Get-Process | Format-List Path' ,
241+ ],
242+ stdout: ProcessLister .pwsh,
243+ ),
244+ ],
245+ )..excludedExecutables.add (ProcessLister .powershell),
246+ );
247+
248+ try {
249+ final ProcessResult result = await processLister.getProcessesWithPath ();
250+ expect (result.stdout, ProcessLister .pwsh);
251+ // ignore: avoid_catches_without_on_clauses
252+ } catch (e) {
253+ fail ('Unexpected exception: $e ' );
254+ }
255+ });
256+
257+ testWithoutContext ('getProcessesWithPath throws if both powershell and pwsh are not on PATH' , () async {
258+ final ProcessLister processLister = ProcessLister (
259+ FakeProcessManager .empty ()..excludedExecutables.addAll (
260+ < String > [
261+ ProcessLister .powershell,
262+ ProcessLister .pwsh,
263+ ],
264+ ),
265+ );
266+
267+ try {
268+ final ProcessResult result = await processLister.getProcessesWithPath ();
269+ fail ('Should have thrown, but successfully ran ${result .stdout }' );
270+ } on StateError {
271+ // Expected
272+ // ignore: avoid_catches_without_on_clauses
273+ } catch (e) {
274+ fail ('Unexpected exception: $e ' );
275+ }
276+ });
172277}
0 commit comments