@@ -9,8 +9,10 @@ import 'package:flutter_tools/src/base/platform.dart';
9
9
import 'package:flutter_tools/src/cache.dart' ;
10
10
import 'package:flutter_tools/src/commands/build.dart' ;
11
11
import 'package:flutter_tools/src/commands/build_ios.dart' ;
12
+ import 'package:flutter_tools/src/ios/plist_parser.dart' ;
12
13
import 'package:flutter_tools/src/ios/xcodeproj.dart' ;
13
14
import 'package:flutter_tools/src/reporting/reporting.dart' ;
15
+ import 'package:test/fake.dart' ;
14
16
15
17
import '../../general.shard/ios/xcresult_test_data.dart' ;
16
18
import '../../src/common.dart' ;
@@ -50,10 +52,20 @@ final Platform notMacosPlatform = FakePlatform(
50
52
}
51
53
);
52
54
55
+ class FakePlistUtils extends Fake implements PlistParser {
56
+ final Map <String , Map <String , Object >> fileContents = < String , Map <String , Object >> {};
57
+
58
+ @override
59
+ String ? getStringValueFromFile (String plistFilePath, String key) {
60
+ return fileContents[plistFilePath]! [key] as String ? ;
61
+ }
62
+ }
63
+
53
64
void main () {
54
65
late FileSystem fileSystem;
55
66
late TestUsage usage;
56
67
late FakeProcessManager fakeProcessManager;
68
+ late FakePlistUtils plistUtils;
57
69
58
70
setUpAll (() {
59
71
Cache .disableLocking ();
@@ -63,6 +75,7 @@ void main() {
63
75
fileSystem = MemoryFileSystem .test ();
64
76
usage = TestUsage ();
65
77
fakeProcessManager = FakeProcessManager .empty ();
78
+ plistUtils = FakePlistUtils ();
66
79
});
67
80
68
81
// Sets up the minimal mock project files necessary to look like a Flutter project.
@@ -246,8 +259,7 @@ void main() {
246
259
FileSystem : () => fileSystem,
247
260
ProcessManager : () => FakeProcessManager .any (),
248
261
Platform : () => macosPlatform,
249
- XcodeProjectInterpreter : () =>
250
- FakeXcodeProjectInterpreterWithBuildSettings (),
262
+ XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
251
263
});
252
264
253
265
testUsingContext ('ipa build fails when --export-options-plist and --export-method are used together' , () async {
@@ -270,8 +282,7 @@ void main() {
270
282
FileSystem : () => fileSystem,
271
283
ProcessManager : () => FakeProcessManager .any (),
272
284
Platform : () => macosPlatform,
273
- XcodeProjectInterpreter : () =>
274
- FakeXcodeProjectInterpreterWithBuildSettings (),
285
+ XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
275
286
});
276
287
277
288
testUsingContext ('ipa build reports when IPA fails' , () async {
@@ -521,8 +532,7 @@ void main() {
521
532
FileSystem : () => fileSystem,
522
533
ProcessManager : () => FakeProcessManager .any (),
523
534
Platform : () => macosPlatform,
524
- XcodeProjectInterpreter : () =>
525
- FakeXcodeProjectInterpreterWithBuildSettings (),
535
+ XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
526
536
});
527
537
528
538
testUsingContext ('Performs code size analysis and sends analytics' , () async {
@@ -601,8 +611,7 @@ void main() {
601
611
FileSystem : () => fileSystem,
602
612
ProcessManager : () => fakeProcessManager,
603
613
Platform : () => macosPlatform,
604
- XcodeProjectInterpreter : () =>
605
- FakeXcodeProjectInterpreterWithBuildSettings (),
614
+ XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
606
615
});
607
616
608
617
testUsingContext ('Trace error if xcresult is empty.' , () async {
@@ -735,6 +744,97 @@ void main() {
735
744
Platform : () => macosPlatform,
736
745
XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
737
746
});
747
+
748
+ testUsingContext (
749
+ 'Validate basic Xcode settings with missing settings' , () async {
750
+
751
+ const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist' ;
752
+ fakeProcessManager.addCommands (< FakeCommand > [
753
+ xattrCommand,
754
+ setUpFakeXcodeBuildHandler (onRun: () {
755
+ fileSystem.file (plistPath).createSync (recursive: true );
756
+ }),
757
+ exportArchiveCommand (exportOptionsPlist: _exportOptionsPlist),
758
+ ]);
759
+
760
+ createMinimalMockProjectFiles ();
761
+
762
+ plistUtils.fileContents[plistPath] = < String ,String > {
763
+ 'CFBundleIdentifier' : 'io.flutter.someProject' ,
764
+ };
765
+
766
+ final BuildCommand command = BuildCommand ();
767
+ await createTestCommandRunner (command).run (
768
+ < String > ['build' , 'ipa' , '--no-pub' ]);
769
+
770
+ expect (
771
+ testLogger.statusText,
772
+ contains (
773
+ '┌─ App Settings ────────────────────────────────────────┐\n '
774
+ '│ Version Number: Missing │\n '
775
+ '│ Build Number: Missing │\n '
776
+ '│ Display Name: Missing │\n '
777
+ '│ Deployment Target: Missing │\n '
778
+ '│ Bundle Identifier: io.flutter.someProject │\n '
779
+ '│ │\n '
780
+ '│ You must set up the missing settings │\n '
781
+ '│ Instructions: https://docs.flutter.dev/deployment/ios │\n '
782
+ '└───────────────────────────────────────────────────────┘'
783
+ )
784
+ );
785
+ }, overrides: < Type , Generator > {
786
+ FileSystem : () => fileSystem,
787
+ ProcessManager : () => fakeProcessManager,
788
+ Platform : () => macosPlatform,
789
+ XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
790
+ PlistParser : () => plistUtils,
791
+ });
792
+
793
+ testUsingContext (
794
+ 'Validate basic Xcode settings with full settings' , () async {
795
+ const String plistPath = 'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist' ;
796
+ fakeProcessManager.addCommands (< FakeCommand > [
797
+ xattrCommand,
798
+ setUpFakeXcodeBuildHandler (onRun: () {
799
+ fileSystem.file (plistPath).createSync (recursive: true );
800
+ }),
801
+ exportArchiveCommand (exportOptionsPlist: _exportOptionsPlist),
802
+ ]);
803
+
804
+ createMinimalMockProjectFiles ();
805
+
806
+ plistUtils.fileContents[plistPath] = < String ,String > {
807
+ 'CFBundleIdentifier' : 'io.flutter.someProject' ,
808
+ 'CFBundleDisplayName' : 'Awesome Gallery' ,
809
+ 'MinimumOSVersion' : '11.0' ,
810
+ 'CFBundleVersion' : '666' ,
811
+ 'CFBundleShortVersionString' : '12.34.56' ,
812
+ };
813
+
814
+ final BuildCommand command = BuildCommand ();
815
+ await createTestCommandRunner (command).run (
816
+ < String > ['build' , 'ipa' , '--no-pub' ]);
817
+
818
+ expect (
819
+ testLogger.statusText,
820
+ contains (
821
+ '┌─ App Settings ────────────────────────────┐\n '
822
+ '│ Version Number: 12.34.56 │\n '
823
+ '│ Build Number: 666 │\n '
824
+ '│ Display Name: Awesome Gallery │\n '
825
+ '│ Deployment Target: 11.0 │\n '
826
+ '│ Bundle Identifier: io.flutter.someProject │\n '
827
+ '└───────────────────────────────────────────┘\n '
828
+ )
829
+ );
830
+ }, overrides: < Type , Generator > {
831
+ FileSystem : () => fileSystem,
832
+ ProcessManager : () => fakeProcessManager,
833
+ Platform : () => macosPlatform,
834
+ XcodeProjectInterpreter : () => FakeXcodeProjectInterpreterWithBuildSettings (),
835
+ PlistParser : () => plistUtils,
836
+ });
837
+
738
838
}
739
839
740
840
const String _xcBundleFilePath = '/.tmp_rand0/flutter_ios_build_temp_dirrand0/temporary_xcresult_bundle' ;
0 commit comments