1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'dart:convert'; |
6 | |
7 | import 'package:file_testing/file_testing.dart' ; |
8 | import 'package:flutter_tools/src/base/error_handling_io.dart'; |
9 | import 'package:flutter_tools/src/base/file_system.dart'; |
10 | |
11 | import '../src/common.dart'; |
12 | import 'swift_package_manager_utils.dart'; |
13 | import 'test_utils.dart'; |
14 | |
15 | void main() { |
16 | final List<String> platforms = <String>['ios' , 'macos' ]; |
17 | for (final String platformName in platforms) { |
18 | final List<String> iosLanguages = <String>[if (platformName == 'ios' ) 'objc' , 'swift' ]; |
19 | final SwiftPackageManagerPlugin integrationTestPlugin = |
20 | SwiftPackageManagerUtils.integrationTestPlugin(platformName); |
21 | |
22 | for (final String iosLanguage in iosLanguages) { |
23 | test( |
24 | 'Swift Package Manager integration for $platformName with $iosLanguage' , |
25 | () async { |
26 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
27 | 'swift_package_manager_enabled.' , |
28 | ); |
29 | final String workingDirectoryPath = workingDirectory.path; |
30 | |
31 | addTearDown(() async { |
32 | await SwiftPackageManagerUtils.disableSwiftPackageManager( |
33 | flutterBin, |
34 | workingDirectoryPath, |
35 | ); |
36 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
37 | }); |
38 | |
39 | // Create and build an app using the CocoaPods version of |
40 | // integration_test. |
41 | await SwiftPackageManagerUtils.disableSwiftPackageManager( |
42 | flutterBin, |
43 | workingDirectoryPath, |
44 | ); |
45 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
46 | flutterBin, |
47 | workingDirectoryPath, |
48 | iosLanguage: iosLanguage, |
49 | platform: platformName, |
50 | usesSwiftPackageManager: true, |
51 | options: <String>['--platforms= $platformName' ], |
52 | ); |
53 | SwiftPackageManagerUtils.addDependency( |
54 | appDirectoryPath: appDirectoryPath, |
55 | plugin: integrationTestPlugin, |
56 | ); |
57 | await SwiftPackageManagerUtils.buildApp( |
58 | flutterBin, |
59 | appDirectoryPath, |
60 | options: <String>[platformName, '--debug' , '-v' ], |
61 | expectedLines: SwiftPackageManagerUtils.expectedLines( |
62 | platform: platformName, |
63 | appDirectoryPath: appDirectoryPath, |
64 | cocoaPodsPlugin: integrationTestPlugin, |
65 | ), |
66 | unexpectedLines: SwiftPackageManagerUtils.unexpectedLines( |
67 | platform: platformName, |
68 | appDirectoryPath: appDirectoryPath, |
69 | cocoaPodsPlugin: integrationTestPlugin, |
70 | ), |
71 | ); |
72 | expect( |
73 | fileSystem |
74 | .directory(appDirectoryPath) |
75 | .childDirectory(platformName) |
76 | .childFile('Podfile' ), |
77 | exists, |
78 | ); |
79 | expect( |
80 | fileSystem |
81 | .directory(appDirectoryPath) |
82 | .childDirectory(platformName) |
83 | .childDirectory('Flutter' ) |
84 | .childDirectory('ephemeral' ) |
85 | .childDirectory('Packages' ) |
86 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ), |
87 | isNot(exists), |
88 | ); |
89 | |
90 | final SwiftPackageManagerPlugin createdCocoaPodsPlugin = |
91 | await SwiftPackageManagerUtils.createPlugin( |
92 | flutterBin, |
93 | workingDirectoryPath, |
94 | platform: platformName, |
95 | iosLanguage: iosLanguage, |
96 | ); |
97 | |
98 | // Rebuild app with Swift Package Manager enabled, migrating the app and using the Swift Package Manager version of |
99 | // integration_test. |
100 | await SwiftPackageManagerUtils.enableSwiftPackageManager( |
101 | flutterBin, |
102 | workingDirectoryPath, |
103 | ); |
104 | await SwiftPackageManagerUtils.buildApp( |
105 | flutterBin, |
106 | appDirectoryPath, |
107 | options: <String>[platformName, '--debug' , '-v' ], |
108 | expectedLines: SwiftPackageManagerUtils.expectedLines( |
109 | platform: platformName, |
110 | appDirectoryPath: appDirectoryPath, |
111 | swiftPackageMangerEnabled: true, |
112 | swiftPackagePlugin: integrationTestPlugin, |
113 | migrated: true, |
114 | ), |
115 | unexpectedLines: SwiftPackageManagerUtils.unexpectedLines( |
116 | platform: platformName, |
117 | appDirectoryPath: appDirectoryPath, |
118 | swiftPackageMangerEnabled: true, |
119 | swiftPackagePlugin: integrationTestPlugin, |
120 | migrated: true, |
121 | ), |
122 | ); |
123 | |
124 | expect( |
125 | fileSystem |
126 | .directory(appDirectoryPath) |
127 | .childDirectory(platformName) |
128 | .childFile('Podfile' ), |
129 | exists, |
130 | ); |
131 | expect( |
132 | fileSystem |
133 | .directory(appDirectoryPath) |
134 | .childDirectory(platformName) |
135 | .childDirectory('Flutter' ) |
136 | .childDirectory('ephemeral' ) |
137 | .childDirectory('Packages' ) |
138 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ), |
139 | exists, |
140 | ); |
141 | |
142 | // Build an app using both a CocoaPods and Swift Package Manager plugin. |
143 | SwiftPackageManagerUtils.addDependency( |
144 | appDirectoryPath: appDirectoryPath, |
145 | plugin: createdCocoaPodsPlugin, |
146 | ); |
147 | await SwiftPackageManagerUtils.buildApp( |
148 | flutterBin, |
149 | appDirectoryPath, |
150 | options: <String>[platformName, '--debug' , '-v' ], |
151 | expectedLines: SwiftPackageManagerUtils.expectedLines( |
152 | platform: platformName, |
153 | appDirectoryPath: appDirectoryPath, |
154 | cocoaPodsPlugin: createdCocoaPodsPlugin, |
155 | swiftPackageMangerEnabled: true, |
156 | swiftPackagePlugin: integrationTestPlugin, |
157 | ), |
158 | unexpectedLines: SwiftPackageManagerUtils.unexpectedLines( |
159 | platform: platformName, |
160 | appDirectoryPath: appDirectoryPath, |
161 | cocoaPodsPlugin: createdCocoaPodsPlugin, |
162 | swiftPackageMangerEnabled: true, |
163 | swiftPackagePlugin: integrationTestPlugin, |
164 | ), |
165 | ); |
166 | |
167 | expect( |
168 | fileSystem |
169 | .directory(appDirectoryPath) |
170 | .childDirectory(platformName) |
171 | .childFile('Podfile' ), |
172 | exists, |
173 | ); |
174 | expect( |
175 | fileSystem |
176 | .directory(appDirectoryPath) |
177 | .childDirectory(platformName) |
178 | .childDirectory('Flutter' ) |
179 | .childDirectory('ephemeral' ) |
180 | .childDirectory('Packages' ) |
181 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ), |
182 | exists, |
183 | ); |
184 | |
185 | // Build app again but with Swift Package Manager disabled by config. |
186 | // App will now use CocoaPods version of integration_test plugin. |
187 | await SwiftPackageManagerUtils.disableSwiftPackageManager( |
188 | flutterBin, |
189 | workingDirectoryPath, |
190 | ); |
191 | await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath); |
192 | await SwiftPackageManagerUtils.buildApp( |
193 | flutterBin, |
194 | appDirectoryPath, |
195 | options: <String>[platformName, '--debug' , '-v' ], |
196 | expectedLines: SwiftPackageManagerUtils.expectedLines( |
197 | platform: platformName, |
198 | appDirectoryPath: appDirectoryPath, |
199 | cocoaPodsPlugin: integrationTestPlugin, |
200 | ), |
201 | unexpectedLines: SwiftPackageManagerUtils.unexpectedLines( |
202 | platform: platformName, |
203 | appDirectoryPath: appDirectoryPath, |
204 | cocoaPodsPlugin: integrationTestPlugin, |
205 | ), |
206 | ); |
207 | |
208 | // Build app again but with Swift Package Manager disabled by pubspec. |
209 | // App will still use CocoaPods version of integration_test plugin. |
210 | await SwiftPackageManagerUtils.enableSwiftPackageManager( |
211 | flutterBin, |
212 | workingDirectoryPath, |
213 | ); |
214 | await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath); |
215 | SwiftPackageManagerUtils.disableSwiftPackageManagerByPubspec( |
216 | appDirectoryPath: appDirectoryPath, |
217 | ); |
218 | await SwiftPackageManagerUtils.buildApp( |
219 | flutterBin, |
220 | appDirectoryPath, |
221 | options: <String>[platformName, '--debug' , '-v' ], |
222 | expectedLines: SwiftPackageManagerUtils.expectedLines( |
223 | platform: platformName, |
224 | appDirectoryPath: appDirectoryPath, |
225 | cocoaPodsPlugin: integrationTestPlugin, |
226 | ), |
227 | unexpectedLines: SwiftPackageManagerUtils.unexpectedLines( |
228 | platform: platformName, |
229 | appDirectoryPath: appDirectoryPath, |
230 | cocoaPodsPlugin: integrationTestPlugin, |
231 | ), |
232 | ); |
233 | }, |
234 | skip: !platform.isMacOS, // [intended] Swift Package Manager only works on macos. |
235 | ); |
236 | } |
237 | |
238 | test('Build $platformName-framework with non-module app uses CocoaPods' , () async { |
239 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
240 | 'swift_package_manager_build_framework.' , |
241 | ); |
242 | final String workingDirectoryPath = workingDirectory.path; |
243 | |
244 | addTearDown(() async { |
245 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
246 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
247 | }); |
248 | |
249 | // Create and build an app using the Swift Package Manager version of |
250 | // integration_test. |
251 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
252 | |
253 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
254 | flutterBin, |
255 | workingDirectoryPath, |
256 | iosLanguage: 'swift' , |
257 | platform: platformName, |
258 | usesSwiftPackageManager: true, |
259 | options: <String>['--platforms= $platformName' ], |
260 | ); |
261 | SwiftPackageManagerUtils.addDependency( |
262 | appDirectoryPath: appDirectoryPath, |
263 | plugin: integrationTestPlugin, |
264 | ); |
265 | |
266 | await SwiftPackageManagerUtils.buildApp( |
267 | flutterBin, |
268 | appDirectoryPath, |
269 | options: <String>[platformName, '--config-only' , '-v' ], |
270 | ); |
271 | |
272 | expect( |
273 | fileSystem.directory(appDirectoryPath).childDirectory(platformName).childFile('Podfile' ), |
274 | isNot(exists), |
275 | ); |
276 | expect( |
277 | fileSystem |
278 | .directory(appDirectoryPath) |
279 | .childDirectory(platformName) |
280 | .childDirectory('Flutter' ) |
281 | .childDirectory('ephemeral' ) |
282 | .childDirectory('Packages' ) |
283 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ), |
284 | exists, |
285 | ); |
286 | |
287 | // Create and build framework using the CocoaPods version of |
288 | // integration_test even though Swift Package Manager is enabled. |
289 | await SwiftPackageManagerUtils.buildApp( |
290 | flutterBin, |
291 | appDirectoryPath, |
292 | options: <String>[' $platformName-framework' , '--no-debug' , '--no-profile' , '-v' ], |
293 | expectedLines: <String>[ |
294 | 'Swift Package Manager does not yet support this command. CocoaPods will be used instead.' , |
295 | ], |
296 | ); |
297 | |
298 | expect( |
299 | fileSystem |
300 | .directory(appDirectoryPath) |
301 | .childDirectory('build' ) |
302 | .childDirectory(platformName) |
303 | .childDirectory('framework' ) |
304 | .childDirectory('Release' ) |
305 | .childDirectory(' ${integrationTestPlugin.pluginName}.xcframework' ), |
306 | exists, |
307 | ); |
308 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
309 | |
310 | test( |
311 | 'Caches build targets between builds with Swift Package Manager on $platformName' , |
312 | () async { |
313 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
314 | 'swift_package_manager_caching.' , |
315 | ); |
316 | final String workingDirectoryPath = workingDirectory.path; |
317 | |
318 | addTearDown(() async { |
319 | await SwiftPackageManagerUtils.disableSwiftPackageManager( |
320 | flutterBin, |
321 | workingDirectoryPath, |
322 | ); |
323 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
324 | }); |
325 | |
326 | // Create and build an app using the Swift Package Manager version of |
327 | // integration_test. |
328 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
329 | |
330 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
331 | flutterBin, |
332 | workingDirectoryPath, |
333 | iosLanguage: 'swift' , |
334 | platform: platformName, |
335 | usesSwiftPackageManager: true, |
336 | options: <String>['--platforms= $platformName' ], |
337 | ); |
338 | SwiftPackageManagerUtils.addDependency( |
339 | appDirectoryPath: appDirectoryPath, |
340 | plugin: integrationTestPlugin, |
341 | ); |
342 | |
343 | final String unpackTarget = 'debug_unpack_ $platformName' ; |
344 | final String bundleFlutterAssetsTarget = 'debug_ ${platformName}_bundle_flutter_assets' ; |
345 | final bool noCodesign = platformName == 'ios' ; |
346 | await SwiftPackageManagerUtils.buildApp( |
347 | flutterBin, |
348 | appDirectoryPath, |
349 | options: <String>[platformName, '--debug' , '-v' , if (noCodesign) '--no-codesign' ], |
350 | expectedLines: <Pattern>[ |
351 | r'SchemeAction Run\ Prepare\ Flutter\ Framework\ Script' , |
352 | ' $unpackTarget: Starting due to' , |
353 | '-dPreBuildAction=PrepareFramework $unpackTarget' , |
354 | ], |
355 | unexpectedLines: <String>[], |
356 | ); |
357 | |
358 | await SwiftPackageManagerUtils.buildApp( |
359 | flutterBin, |
360 | appDirectoryPath, |
361 | options: <String>[platformName, '--debug' , '-v' , if (noCodesign) '--no-codesign' ], |
362 | expectedLines: <Pattern>[ |
363 | r'SchemeAction Run\ Prepare\ Flutter\ Framework\ Script' , |
364 | 'Skipping target: $unpackTarget' , |
365 | 'Skipping target: $bundleFlutterAssetsTarget' , |
366 | ], |
367 | unexpectedLines: <String>['Starting due to' ], |
368 | ); |
369 | }, |
370 | skip: !platform.isMacOS, // [intended] Swift Package Manager only works on macos. |
371 | ); |
372 | } |
373 | |
374 | test('Build ios-framework with module app uses CocoaPods' , () async { |
375 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
376 | 'swift_package_manager_build_framework_module.' , |
377 | ); |
378 | final String workingDirectoryPath = workingDirectory.path; |
379 | |
380 | addTearDown(() async { |
381 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
382 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
383 | }); |
384 | |
385 | // Create and build module and framework using the CocoaPods version of |
386 | // integration_test even though Swift Package Manager is enabled. |
387 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
388 | |
389 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
390 | flutterBin, |
391 | workingDirectoryPath, |
392 | iosLanguage: 'swift' , |
393 | platform: 'ios' , |
394 | usesSwiftPackageManager: true, |
395 | options: <String>['--template=module' ], |
396 | ); |
397 | final SwiftPackageManagerPlugin integrationTestPlugin = |
398 | SwiftPackageManagerUtils.integrationTestPlugin('ios' ); |
399 | SwiftPackageManagerUtils.addDependency( |
400 | appDirectoryPath: appDirectoryPath, |
401 | plugin: integrationTestPlugin, |
402 | ); |
403 | |
404 | await SwiftPackageManagerUtils.buildApp( |
405 | flutterBin, |
406 | appDirectoryPath, |
407 | options: <String>['ios' , '--config-only' , '-v' ], |
408 | ); |
409 | |
410 | expect( |
411 | fileSystem.directory(appDirectoryPath).childDirectory('.ios' ).childFile('Podfile' ), |
412 | exists, |
413 | ); |
414 | expect( |
415 | fileSystem |
416 | .directory(appDirectoryPath) |
417 | .childDirectory('.ios' ) |
418 | .childDirectory('Flutter' ) |
419 | .childDirectory('ephemeral' ) |
420 | .childDirectory('Packages' ) |
421 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ), |
422 | isNot(exists), |
423 | ); |
424 | final File pbxprojFile = fileSystem |
425 | .directory(appDirectoryPath) |
426 | .childDirectory('.ios' ) |
427 | .childDirectory('Runner.xcodeproj' ) |
428 | .childFile('project.pbxproj' ); |
429 | expect(pbxprojFile, exists); |
430 | expect(pbxprojFile.readAsStringSync(), isNot(contains('FlutterGeneratedPluginSwiftPackage' ))); |
431 | final File xcschemeFile = fileSystem |
432 | .directory(appDirectoryPath) |
433 | .childDirectory('.ios' ) |
434 | .childDirectory('Runner.xcodeproj' ) |
435 | .childDirectory('xcshareddata' ) |
436 | .childDirectory('xcschemes' ) |
437 | .childFile('Runner.xcscheme' ); |
438 | expect(xcschemeFile, exists); |
439 | expect( |
440 | xcschemeFile.readAsStringSync(), |
441 | isNot(contains('Run Prepare Flutter Framework Script' )), |
442 | ); |
443 | |
444 | await SwiftPackageManagerUtils.buildApp( |
445 | flutterBin, |
446 | appDirectoryPath, |
447 | options: <String>['ios-framework' , '--no-debug' , '--no-profile' , '-v' ], |
448 | unexpectedLines: <String>[ |
449 | 'Adding Swift Package Manager integration...' , |
450 | 'Swift Package Manager does not yet support this command. CocoaPods will be used instead.' , |
451 | ], |
452 | ); |
453 | |
454 | expect( |
455 | fileSystem |
456 | .directory(appDirectoryPath) |
457 | .childDirectory('build' ) |
458 | .childDirectory('ios' ) |
459 | .childDirectory('framework' ) |
460 | .childDirectory('Release' ) |
461 | .childDirectory(' ${integrationTestPlugin.pluginName}.xcframework' ), |
462 | exists, |
463 | ); |
464 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
465 | |
466 | test('Build ios-framework with non module app uses CocoaPods' , () async { |
467 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
468 | 'swift_package_manager_build_framework_non_module.' , |
469 | ); |
470 | final String workingDirectoryPath = workingDirectory.path; |
471 | |
472 | addTearDown(() async { |
473 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
474 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
475 | }); |
476 | |
477 | // Create and build a regular app and framework using the CocoaPods version of |
478 | // integration_test even though Swift Package Manager is enabled. |
479 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
480 | |
481 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
482 | flutterBin, |
483 | workingDirectoryPath, |
484 | iosLanguage: 'swift' , |
485 | platform: 'ios' , |
486 | usesSwiftPackageManager: true, |
487 | options: <String>[], |
488 | ); |
489 | final SwiftPackageManagerPlugin integrationTestPlugin = |
490 | SwiftPackageManagerUtils.integrationTestPlugin('ios' ); |
491 | SwiftPackageManagerUtils.addDependency( |
492 | appDirectoryPath: appDirectoryPath, |
493 | plugin: integrationTestPlugin, |
494 | ); |
495 | |
496 | await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath); |
497 | |
498 | await SwiftPackageManagerUtils.buildApp( |
499 | flutterBin, |
500 | appDirectoryPath, |
501 | options: <String>['ios-framework' , '--xcframework' , '--no-debug' , '--no-profile' , '-v' ], |
502 | expectedLines: <String>[ |
503 | 'Swift Package Manager does not yet support this command. CocoaPods will be used instead.' , |
504 | ], |
505 | unexpectedLines: <String>['Adding Swift Package Manager integration...' ], |
506 | ); |
507 | |
508 | expect(fileSystem.directory(appDirectoryPath).childDirectory('.ios' ), isNot(exists)); |
509 | |
510 | // Verify the generated Swift Package Manager manifest file has no dependencies. |
511 | final File generatedManifestFile = fileSystem |
512 | .directory(appDirectoryPath) |
513 | .childDirectory('ios' ) |
514 | .childDirectory('Flutter' ) |
515 | .childDirectory('ephemeral' ) |
516 | .childDirectory('Packages' ) |
517 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ) |
518 | .childFile('Package.swift' ); |
519 | |
520 | expect(generatedManifestFile, exists); |
521 | |
522 | final String generatedManifest = generatedManifestFile.readAsStringSync(); |
523 | const String expected = 'dependencies: [\n \n ],\n' ; |
524 | expect(generatedManifest, contains(expected)); |
525 | |
526 | expect( |
527 | fileSystem |
528 | .directory(appDirectoryPath) |
529 | .childDirectory('build' ) |
530 | .childDirectory('ios' ) |
531 | .childDirectory('framework' ) |
532 | .childDirectory('Release' ) |
533 | .childDirectory(' ${integrationTestPlugin.pluginName}.xcframework' ), |
534 | exists, |
535 | ); |
536 | |
537 | final File flutterPluginsDependenciesFile = fileSystem |
538 | .directory(appDirectoryPath) |
539 | .childFile('.flutter-plugins-dependencies' ); |
540 | |
541 | expect(flutterPluginsDependenciesFile, exists); |
542 | |
543 | final String dependenciesString = flutterPluginsDependenciesFile.readAsStringSync(); |
544 | final Map<String, dynamic>? dependenciesJson = |
545 | json.decode(dependenciesString) as Map<String, dynamic>?; |
546 | final Map<String, dynamic>? swiftPackageManagerEnabled = |
547 | dependenciesJson?['swift_package_manager_enabled' ] as Map<String, dynamic>?; |
548 | final bool? swiftPackageManagerEnabledIos = swiftPackageManagerEnabled?['ios' ] as bool?; |
549 | |
550 | expect(swiftPackageManagerEnabledIos, isFalse); |
551 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
552 | |
553 | test("Generated Swift package uses iOS's project minimum deployment" , () async { |
554 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
555 | 'swift_package_manager_minimum_deployment_ios.' , |
556 | ); |
557 | final String workingDirectoryPath = workingDirectory.path; |
558 | |
559 | addTearDown(() async { |
560 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
561 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
562 | }); |
563 | |
564 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
565 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
566 | flutterBin, |
567 | workingDirectoryPath, |
568 | iosLanguage: 'swift' , |
569 | platform: 'ios' , |
570 | usesSwiftPackageManager: true, |
571 | options: <String>['--platforms=ios' ], |
572 | ); |
573 | |
574 | // Modify the project to raise the deployment version. |
575 | final File projectFile = fileSystem |
576 | .directory(appDirectoryPath) |
577 | .childDirectory('ios' ) |
578 | .childDirectory('Runner.xcodeproj' ) |
579 | .childFile('project.pbxproj' ); |
580 | |
581 | final String oldProject = projectFile.readAsStringSync(); |
582 | final String newProject = oldProject.replaceAll( |
583 | RegExp(r'IPHONEOS_DEPLOYMENT_TARGET = \d+\.\d+;' ), |
584 | 'IPHONEOS_DEPLOYMENT_TARGET = 15.1;' , |
585 | ); |
586 | |
587 | projectFile.writeAsStringSync(newProject); |
588 | |
589 | // Build the app. This generates Flutter's Swift package. |
590 | await SwiftPackageManagerUtils.buildApp( |
591 | flutterBin, |
592 | appDirectoryPath, |
593 | options: <String>['ios' , '--debug' , '-v' ], |
594 | ); |
595 | |
596 | // Verify the generated Swift package uses the project's minimum deployment. |
597 | final File generatedManifestFile = fileSystem |
598 | .directory(appDirectoryPath) |
599 | .childDirectory('ios' ) |
600 | .childDirectory('Flutter' ) |
601 | .childDirectory('ephemeral' ) |
602 | .childDirectory('Packages' ) |
603 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ) |
604 | .childFile('Package.swift' ); |
605 | |
606 | expect(generatedManifestFile, exists); |
607 | |
608 | final String generatedManifest = generatedManifestFile.readAsStringSync(); |
609 | const String expected = ''' |
610 | platforms: [ |
611 | .iOS("15.1") |
612 | ], |
613 | ''' ; |
614 | |
615 | expect(generatedManifest.contains(expected), isTrue); |
616 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
617 | |
618 | test("Generated Swift package uses macOS's project minimum deployment" , () async { |
619 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
620 | 'swift_package_manager_minimum_deployment_macos.' , |
621 | ); |
622 | final String workingDirectoryPath = workingDirectory.path; |
623 | |
624 | addTearDown(() async { |
625 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
626 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
627 | }); |
628 | |
629 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
630 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
631 | flutterBin, |
632 | workingDirectoryPath, |
633 | iosLanguage: 'swift' , |
634 | platform: 'macos' , |
635 | usesSwiftPackageManager: true, |
636 | options: <String>['--platforms=macos' ], |
637 | ); |
638 | |
639 | // Modify the project to raise the deployment version. |
640 | final File projectFile = fileSystem |
641 | .directory(appDirectoryPath) |
642 | .childDirectory('macos' ) |
643 | .childDirectory('Runner.xcodeproj' ) |
644 | .childFile('project.pbxproj' ); |
645 | |
646 | final String oldProject = projectFile.readAsStringSync(); |
647 | final String newProject = oldProject.replaceAll( |
648 | RegExp(r'MACOSX_DEPLOYMENT_TARGET = \d+\.\d+;' ), |
649 | 'MACOSX_DEPLOYMENT_TARGET = 15.1;' , |
650 | ); |
651 | |
652 | projectFile.writeAsStringSync(newProject); |
653 | |
654 | // Build the app. This generates Flutter's Swift package. |
655 | await SwiftPackageManagerUtils.buildApp( |
656 | flutterBin, |
657 | appDirectoryPath, |
658 | options: <String>['macos' , '--debug' , '-v' ], |
659 | ); |
660 | |
661 | // Verify the generated Swift package uses the project's minimum deployment. |
662 | final File generatedManifestFile = fileSystem |
663 | .directory(appDirectoryPath) |
664 | .childDirectory('macos' ) |
665 | .childDirectory('Flutter' ) |
666 | .childDirectory('ephemeral' ) |
667 | .childDirectory('Packages' ) |
668 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ) |
669 | .childFile('Package.swift' ); |
670 | |
671 | expect(generatedManifestFile, exists); |
672 | |
673 | final String generatedManifest = generatedManifestFile.readAsStringSync(); |
674 | const String expected = ''' |
675 | platforms: [ |
676 | .macOS("15.1") |
677 | ], |
678 | ''' ; |
679 | |
680 | expect(generatedManifest, contains(expected)); |
681 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
682 | |
683 | test('Removing the last plugin updates the generated Swift package' , () async { |
684 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
685 | 'swift_package_manager_remove_last_plugin.' , |
686 | ); |
687 | final String workingDirectoryPath = workingDirectory.path; |
688 | |
689 | addTearDown(() async { |
690 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
691 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
692 | }); |
693 | |
694 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
695 | |
696 | // Create an app with a plugin. |
697 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
698 | flutterBin, |
699 | workingDirectoryPath, |
700 | iosLanguage: 'swift' , |
701 | platform: 'ios' , |
702 | usesSwiftPackageManager: true, |
703 | options: <String>['--platforms=ios' ], |
704 | ); |
705 | |
706 | final SwiftPackageManagerPlugin integrationTestPlugin = |
707 | SwiftPackageManagerUtils.integrationTestPlugin('ios' ); |
708 | |
709 | SwiftPackageManagerUtils.addDependency( |
710 | appDirectoryPath: appDirectoryPath, |
711 | plugin: integrationTestPlugin, |
712 | ); |
713 | |
714 | // Build the app to generate the Swift package. |
715 | await SwiftPackageManagerUtils.buildApp( |
716 | flutterBin, |
717 | appDirectoryPath, |
718 | options: <String>['ios' , '--config-only' , '-v' ], |
719 | ); |
720 | |
721 | // Verify the generated Swift package depends on the plugin. |
722 | final File generatedManifestFile = fileSystem |
723 | .directory(appDirectoryPath) |
724 | .childDirectory('ios' ) |
725 | .childDirectory('Flutter' ) |
726 | .childDirectory('ephemeral' ) |
727 | .childDirectory('Packages' ) |
728 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ) |
729 | .childFile('Package.swift' ); |
730 | |
731 | expect(generatedManifestFile, exists); |
732 | |
733 | String generatedManifest = generatedManifestFile.readAsStringSync(); |
734 | final String generatedSwiftDependency = ''' |
735 | dependencies: [ |
736 | .package(name: "integration_test", path: " ${integrationTestPlugin.swiftPackagePlatformPath}") |
737 | ], |
738 | ''' ; |
739 | |
740 | expect(generatedManifest.contains(generatedSwiftDependency), isTrue); |
741 | |
742 | // Remove the plugin and rebuild the app to re-generate the Swift package. |
743 | SwiftPackageManagerUtils.removeDependency( |
744 | appDirectoryPath: appDirectoryPath, |
745 | plugin: integrationTestPlugin, |
746 | ); |
747 | |
748 | await SwiftPackageManagerUtils.buildApp( |
749 | flutterBin, |
750 | appDirectoryPath, |
751 | options: <String>['ios' , '--config-only' , '-v' ], |
752 | ); |
753 | |
754 | // Verify the generated Swift package does not depend on the plugin. |
755 | expect(generatedManifestFile, exists); |
756 | |
757 | generatedManifest = generatedManifestFile.readAsStringSync(); |
758 | const String emptyDependencies = 'dependencies: [\n \n ],\n' ; |
759 | |
760 | expect(generatedManifest, isNot(contains(generatedSwiftDependency))); |
761 | expect(generatedManifest, contains(emptyDependencies)); |
762 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
763 | |
764 | test('Migrated app builds after Swift Package Manager is turned off' , () async { |
765 | final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync( |
766 | 'swift_package_manager_turned_off.' , |
767 | ); |
768 | final String workingDirectoryPath = workingDirectory.path; |
769 | |
770 | addTearDown(() async { |
771 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
772 | ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true); |
773 | }); |
774 | |
775 | await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath); |
776 | |
777 | // Create an app with a plugin and Swift Package Manager integration. |
778 | final String appDirectoryPath = await SwiftPackageManagerUtils.createApp( |
779 | flutterBin, |
780 | workingDirectoryPath, |
781 | iosLanguage: 'swift' , |
782 | platform: 'ios' , |
783 | usesSwiftPackageManager: true, |
784 | options: <String>['--platforms=ios' ], |
785 | ); |
786 | |
787 | final SwiftPackageManagerPlugin integrationTestPlugin = |
788 | SwiftPackageManagerUtils.integrationTestPlugin('ios' ); |
789 | |
790 | SwiftPackageManagerUtils.addDependency( |
791 | appDirectoryPath: appDirectoryPath, |
792 | plugin: integrationTestPlugin, |
793 | ); |
794 | |
795 | // Build the app. |
796 | await SwiftPackageManagerUtils.buildApp( |
797 | flutterBin, |
798 | appDirectoryPath, |
799 | options: <String>['ios' , '--config-only' , '-v' ], |
800 | ); |
801 | |
802 | // The app should have SwiftPM integration. |
803 | final File xcodeProjectFile = fileSystem |
804 | .directory(appDirectoryPath) |
805 | .childDirectory('ios' ) |
806 | .childDirectory('Runner.xcodeproj' ) |
807 | .childFile('project.pbxproj' ); |
808 | final File generatedManifestFile = fileSystem |
809 | .directory(appDirectoryPath) |
810 | .childDirectory('ios' ) |
811 | .childDirectory('Flutter' ) |
812 | .childDirectory('ephemeral' ) |
813 | .childDirectory('Packages' ) |
814 | .childDirectory('FlutterGeneratedPluginSwiftPackage' ) |
815 | .childFile('Package.swift' ); |
816 | final Directory cocoaPodsPluginFramework = fileSystem |
817 | .directory(appDirectoryPath) |
818 | .childDirectory('build' ) |
819 | .childDirectory('ios' ) |
820 | .childDirectory('iphoneos' ) |
821 | .childDirectory('Runner.app' ) |
822 | .childDirectory('Frameworks' ) |
823 | .childDirectory(' ${integrationTestPlugin.pluginName}.framework' ); |
824 | |
825 | expect(xcodeProjectFile, exists); |
826 | expect(generatedManifestFile, exists); |
827 | expect(cocoaPodsPluginFramework, isNot(exists)); |
828 | |
829 | String xcodeProject = xcodeProjectFile.readAsStringSync(); |
830 | String generatedManifest = generatedManifestFile.readAsStringSync(); |
831 | final String generatedSwiftDependency = ''' |
832 | dependencies: [ |
833 | .package(name: "integration_test", path: " ${integrationTestPlugin.swiftPackagePlatformPath}") |
834 | ], |
835 | ''' ; |
836 | |
837 | expect(xcodeProject, contains('FlutterGeneratedPluginSwiftPackage' )); |
838 | expect(generatedManifest, contains(generatedSwiftDependency)); |
839 | |
840 | // Disable Swift Package Manager and do a clean re-build of the app. |
841 | // The build should succeed. |
842 | await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath); |
843 | |
844 | await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath); |
845 | |
846 | await SwiftPackageManagerUtils.buildApp( |
847 | flutterBin, |
848 | appDirectoryPath, |
849 | options: <String>['ios' , '-v' ], |
850 | ); |
851 | |
852 | // The app should still have SwiftPM integration, |
853 | // but the plugin should be added using CocoaPods. |
854 | expect(xcodeProjectFile, exists); |
855 | expect(generatedManifestFile, exists); |
856 | |
857 | xcodeProject = xcodeProjectFile.readAsStringSync(); |
858 | generatedManifest = generatedManifestFile.readAsStringSync(); |
859 | const String emptyDependencies = 'dependencies: [\n \n ],\n' ; |
860 | |
861 | expect(xcodeProject, contains('FlutterGeneratedPluginSwiftPackage' )); |
862 | expect(generatedManifest, isNot(contains('integration_test' ))); |
863 | expect(generatedManifest, contains(emptyDependencies)); |
864 | expect(cocoaPodsPluginFramework, exists); |
865 | }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. |
866 | } |
867 | |