Skip to content

Commit 09e3e99

Browse files
authored
Merge pull request #2857 from leancodepl/fix/2853-passing-flutter-command-not-work-on-the-web
Fix/2853 passing flutter command not work on the web
2 parents bce7592 + 14386f0 commit 09e3e99

File tree

4 files changed

+251
-14
lines changed

4 files changed

+251
-14
lines changed

packages/patrol_cli/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- Fix a bug when user set a nested test_directory (eg. test/e2e), TestFinder was searching for test files in parent directory instead of project's root (#2858)
44
- Add support for `--no-tree-shake-icons` flag in cli commands (#2704)
5+
- Fix `PATROL_FLUTTER_COMMAND` not being used when building web app. (#2857)
56

67
## 4.0.2
78

packages/patrol_cli/lib/src/crossplatform/app_options.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,4 +429,25 @@ class WebAppOptions {
429429
final int? globalTimeout;
430430
final String? shard;
431431
final String? headless;
432+
433+
/// Translates these options into a proper flutter build invocation.
434+
List<String> toFlutterBuildInvocation() {
435+
final cmd = [
436+
flutter.command.executable,
437+
...flutter.command.arguments,
438+
'build',
439+
'web',
440+
'--target=${flutter.target}',
441+
'--${flutter.buildMode.name}',
442+
// Note: --flavor is not supported for web, so we don't include it
443+
...flutter.dartDefines.entries.map(
444+
(e) => '--dart-define=${e.key}=${e.value}',
445+
),
446+
...flutter.dartDefineFromFilePaths.map(
447+
(e) => '--dart-define-from-file=$e',
448+
),
449+
];
450+
451+
return cmd;
452+
}
432453
}

packages/patrol_cli/lib/src/web/web_test_backend.dart

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,9 @@ class WebTestBackend {
3131
Future<void> build(WebAppOptions options) async {
3232
_logger.detail('Building web app for testing...');
3333

34-
final result = await _processManager.run([
35-
options.flutter.command.executable,
36-
'build',
37-
'web',
38-
'--target=${options.flutter.target}',
39-
'--${options.flutter.buildMode.name}',
40-
// Note: --flavor is not supported for web, so we don't include it
41-
...options.flutter.dartDefines.entries.map(
42-
(e) => '--dart-define=${e.key}=${e.value}',
43-
),
44-
...options.flutter.dartDefineFromFilePaths.map(
45-
(e) => '--dart-define-from-file=$e',
46-
),
47-
]);
34+
final result = await _processManager.run(
35+
options.toFlutterBuildInvocation(),
36+
);
4837

4938
if (result.exitCode != 0) {
5039
throw ProcessException(
@@ -175,6 +164,7 @@ class WebTestBackend {
175164

176165
final process = await _processManager.start([
177166
options.flutter.command.executable,
167+
...options.flutter.command.arguments,
178168
'run',
179169
'-d',
180170
if (develop) 'chrome' else 'web-server',

packages/patrol_cli/test/crossplatform/app_options_test.dart

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,4 +526,229 @@ void main() {
526526
});
527527
});
528528
});
529+
530+
group('WebAppOptions', () {
531+
late WebAppOptions options;
532+
533+
group('correctly encodes Flutter build invocation', () {
534+
test('with minimal configuration', () {
535+
const flutterOpts = FlutterAppOptions(
536+
command: flutterCommand,
537+
target: 'patrol_test/app_test.dart',
538+
buildMode: BuildMode.debug,
539+
flavor: null,
540+
buildName: null,
541+
buildNumber: null,
542+
dartDefines: {},
543+
dartDefineFromFilePaths: [],
544+
);
545+
546+
options = const WebAppOptions(flutter: flutterOpts);
547+
548+
final flutterInvocation = options.toFlutterBuildInvocation();
549+
550+
expect(
551+
flutterInvocation,
552+
equals([
553+
'flutter',
554+
'build',
555+
'web',
556+
'--target=patrol_test/app_test.dart',
557+
'--debug',
558+
]),
559+
);
560+
});
561+
562+
test('with release build mode', () {
563+
const flutterOpts = FlutterAppOptions(
564+
command: flutterCommand,
565+
target: 'integration_test/app_test.dart',
566+
buildMode: BuildMode.release,
567+
flavor: null,
568+
buildName: null,
569+
buildNumber: null,
570+
dartDefines: {},
571+
dartDefineFromFilePaths: [],
572+
);
573+
574+
options = const WebAppOptions(flutter: flutterOpts);
575+
576+
final flutterInvocation = options.toFlutterBuildInvocation();
577+
578+
expect(
579+
flutterInvocation,
580+
equals([
581+
'flutter',
582+
'build',
583+
'web',
584+
'--target=integration_test/app_test.dart',
585+
'--release',
586+
]),
587+
);
588+
});
589+
590+
test('with dart defines', () {
591+
const flutterOpts = FlutterAppOptions(
592+
command: flutterCommand,
593+
target: 'patrol_test/app_test.dart',
594+
buildMode: BuildMode.debug,
595+
flavor: null,
596+
buildName: null,
597+
buildNumber: null,
598+
dartDefines: {
599+
'EMAIL': '[email protected]',
600+
'PASSWORD': 'ny4ncat',
601+
'API_KEY': 'secret123',
602+
},
603+
dartDefineFromFilePaths: [],
604+
);
605+
606+
options = const WebAppOptions(flutter: flutterOpts);
607+
608+
final flutterInvocation = options.toFlutterBuildInvocation();
609+
610+
expect(
611+
flutterInvocation,
612+
equals([
613+
'flutter',
614+
'build',
615+
'web',
616+
'--target=patrol_test/app_test.dart',
617+
'--debug',
618+
619+
'--dart-define=PASSWORD=ny4ncat',
620+
'--dart-define=API_KEY=secret123',
621+
]),
622+
);
623+
});
624+
625+
test('with dart define from file paths', () {
626+
const flutterOpts = FlutterAppOptions(
627+
command: flutterCommand,
628+
target: 'patrol_test/app_test.dart',
629+
buildMode: BuildMode.release,
630+
flavor: null,
631+
buildName: null,
632+
buildNumber: null,
633+
dartDefines: {},
634+
dartDefineFromFilePaths: ['defines.json', 'secrets.env'],
635+
);
636+
637+
options = const WebAppOptions(flutter: flutterOpts);
638+
639+
final flutterInvocation = options.toFlutterBuildInvocation();
640+
641+
expect(
642+
flutterInvocation,
643+
equals([
644+
'flutter',
645+
'build',
646+
'web',
647+
'--target=patrol_test/app_test.dart',
648+
'--release',
649+
'--dart-define-from-file=defines.json',
650+
'--dart-define-from-file=secrets.env',
651+
]),
652+
);
653+
});
654+
655+
test('with both dart defines and dart define from file', () {
656+
const flutterOpts = FlutterAppOptions(
657+
command: flutterCommand,
658+
target: 'patrol_test/web_test.dart',
659+
buildMode: BuildMode.profile,
660+
flavor: null,
661+
buildName: null,
662+
buildNumber: null,
663+
dartDefines: {'ENV': 'production', 'DEBUG_MODE': 'false'},
664+
dartDefineFromFilePaths: ['config.json'],
665+
);
666+
667+
options = const WebAppOptions(flutter: flutterOpts);
668+
669+
final flutterInvocation = options.toFlutterBuildInvocation();
670+
671+
expect(
672+
flutterInvocation,
673+
equals([
674+
'flutter',
675+
'build',
676+
'web',
677+
'--target=patrol_test/web_test.dart',
678+
'--profile',
679+
'--dart-define=ENV=production',
680+
'--dart-define=DEBUG_MODE=false',
681+
'--dart-define-from-file=config.json',
682+
]),
683+
);
684+
});
685+
686+
test('with custom flutter command arguments', () {
687+
const customFlutterCommand = FlutterCommand('flutter', [
688+
'--verbose',
689+
'--no-pub',
690+
]);
691+
692+
const flutterOpts = FlutterAppOptions(
693+
command: customFlutterCommand,
694+
target: 'test/my_test.dart',
695+
buildMode: BuildMode.debug,
696+
flavor: null,
697+
buildName: null,
698+
buildNumber: null,
699+
dartDefines: {},
700+
dartDefineFromFilePaths: [],
701+
);
702+
703+
options = const WebAppOptions(flutter: flutterOpts);
704+
705+
final flutterInvocation = options.toFlutterBuildInvocation();
706+
707+
expect(
708+
flutterInvocation,
709+
equals([
710+
'flutter',
711+
'--verbose',
712+
'--no-pub',
713+
'build',
714+
'web',
715+
'--target=test/my_test.dart',
716+
'--debug',
717+
]),
718+
);
719+
});
720+
721+
test('flavor is ignored for web builds', () {
722+
// Note: Web builds don't support flavors, so this should be handled
723+
// by not including --flavor in the command
724+
const flutterOpts = FlutterAppOptions(
725+
command: flutterCommand,
726+
target: 'patrol_test/app_test.dart',
727+
buildMode: BuildMode.release,
728+
flavor: 'production', // This should be ignored for web
729+
buildName: null,
730+
buildNumber: null,
731+
dartDefines: {},
732+
dartDefineFromFilePaths: [],
733+
);
734+
735+
options = const WebAppOptions(flutter: flutterOpts);
736+
737+
final flutterInvocation = options.toFlutterBuildInvocation();
738+
739+
// Verify that --flavor is NOT included in the invocation
740+
expect(
741+
flutterInvocation,
742+
equals([
743+
'flutter',
744+
'build',
745+
'web',
746+
'--target=patrol_test/app_test.dart',
747+
'--release',
748+
]),
749+
);
750+
expect(flutterInvocation, isNot(contains('--flavor')));
751+
});
752+
});
753+
});
529754
}

0 commit comments

Comments
 (0)